最小表示法
什么是最小表示法,就是说给定一个字符串,每次将字符串的最后一位放在最前面组成新的字符串,叫做循环同构,而这些字符串里面字典序最小的就是最小表示
比如,设s=“abca” 那么他的循环同构字符串有:abca,aabc,caab,bcaa,那么s的最小表示就是aabc
那么我们怎么求呢?最简单的就是朴素算法,按照定义以此比较这个字符串的字典序
那么如何使用最小表示法?
1.初始化i=1,j=2
2.通过扫描的方式比较b[i]与b[j]两个循环同构串
(1)如果扫描了n个字符仍然相等,说明s由1种字符构成,任意b[i]都是他的最小表示法
(2)在i+k与j+k发现不相等
如果ss[i+k]>ss[j+k]那么直接i=i+k+1;如果i=j那么i++
如果ss[i+k]<ss[j+k]那么直接j=j+k+1;如果i=j那么j++
其实最小表示法这种算法比较厉害,比较聪明,发现ss[i+k]>ss[j+k]就不做任何的多余的操作,直接跳过,和KMP还是有一点的像的,也就是说及时排除多余现象,最后保存答案
int n;
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++);
//找到不相等的地方
if(k==n) break;//只有一个字符构成
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);