參考自 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;
}