一、最小表示法:
给定一个字符串S(1----N),如果我们不断把它的最后一个字符放到开头,最终会得到n个字符串,称这n个字符串是循环同构的。这些字符串中字典序最小的一个,称为字符串S的最小表示。
最小表示法求解:
(1)我们先把S复制一份接到它的结尾,得到的字符串记为SS。
(2)初始化 i = 1,j = 2。
(3)通过直接向后扫描的方法,比较b(i)与b(j)两个循环同构串。
如果扫描了n个字符后仍然相等,说明S只由1种字符构成,任意b(i)都是它的最小表示。
如果在 i+k 与 j+k 处发现不相等:
(1)若SS(i+k)>SS(j+k) 令 i=i+k+1。若此时 i=j ,再令 i = i + 1。
(2)若SS(i+k)<SS(j+k) 令j=j+k+1。若此时 j=i,再令 j = j +1。
(4)若i>n,b(j)为最小表示,若j>n,b(i)为最小表示;否则重复第三步。
时间复杂度为O(n)。
int n=strlen(s+1);
for(int i=1;i<=n;i++)
{
s[n+i]=s[i];
}
int i=1,j=2,k;
while(i<=n&&j<=n)
{
for(k=0;k<n&&s[i+k]==s[j+k];k++)
continue;
if(k==n) break;//S只由一个字符构成
if(s[i+k]>s[j+k])
{
i=i+k+1;
if(i==j) i++;
}
else
{
j=j+k+1;
if(i==j) j++;
}
}
ans=min(i,j); //b[ans]是最小表示。