参考自 http://blog.csdn.net/zy691357966/article/details/39854359
最近做题碰到了字符串同构的题,就百度看了一下字符串同构的最小表示法
具体步骤
1,利用两个指针i和j,初始化时i=0,j=1;
2,从k=0开始,检验是s[i+k]与s[j+k]是否相等,如果相等,则k++,一直进行下去,知道找到了第一个的不同(若k试了一个字符串的长度也没找到不同,则原来那个位置就是最小表示,算法终止)则在该过程中,s[i+k]与s[j+k]的大小关系,有三种情况
1 s[i+k]>s[j+k],则是s[i~i+k]不会是这个循环字符串的最小表示前缀。则i=(i+k+1)%len;
证明
2s[i+k]<s[j+k]这时j=j+k+1;
3 s[i+k]=s[j+k],那么k++;if(k==len)结束
最终返回min(i,j);
代码
int minishow(string str)
{
int i = 0;
int j = 1;
int k = 0;
int len = str.length();
while (j < len && i < len && k < len)
{
if (str[(i + k) %len] == str[(j + k)%len ])
{
k++;
}
else
{
if (str[(i + k) %len] > str[(j + k) %len])
{
i = i + k + 1;
}
else
{
j = j + k + 1;
}
if (i == j)
j++;
k = 0;
}
}
return i < j ? i : j;
}
一道简单题
http://acm.hdu.edu.cn/showproblem.php?pid=2609
AC代码
#include<iostream>
#include<string>
#include<set>
using namespace std;
int minishow(string str)
{
int i = 0;
int j = 1;
int k = 0;
int len = str.length();
while (j < len && i < len && k < len)
{
if (str[(i + k) %len] == str[(j + k)%len ])
{
k++;
}
else
{
if (str[(i + k) %len] > str[(j + k) %len])
{
i = i + k + 1;
}
else
{
j = j + k + 1;
}
if (i == j)
j++;
k = 0;
}
}
return i < j ? i : j;
}
int main()
{
int n;
int mini;
string str,s;
set<string>oz;
while (cin >> n)
{
while (n--)
{
cin >> str;
mini = minishow(str);
s = str.substr(mini, str.length() - mini) + str.substr(0, mini);
oz.insert(s);
}
cout << oz.size() << endl;
oz.clear();
}
return 0;
}