C++ 旋转后的字典最小字符串

C++ 旋转后的字典最小字符串,c++,string,algorithm,lexicographic,C++,String,Algorithm,Lexicographic,我正在努力解决这个问题 我需要找到一个给定字符串的旋转次数,这将使它在所有旋转中以字典形式最小 例如: 原件:ama 第一轮:maa 第二次轮换:aam这是词典中最小的轮换,所以答案是2 这是我的密码: string s,tmp; char ss[100002]; scanf("%s",ss); s=ss; tmp=s; int i,len=s.size(),ans=0,t=0; for(i=0;i<len;i++) {

我正在努力解决这个问题

我需要找到一个给定字符串的旋转次数,这将使它在所有旋转中以字典形式最小

例如:

原件:
ama

第一轮:
maa

第二次轮换:
aam
这是词典中最小的轮换,所以答案是2

这是我的密码:

string s,tmp;
    char ss[100002];
    scanf("%s",ss);
    s=ss;
    tmp=s;
    int i,len=s.size(),ans=0,t=0;
    for(i=0;i<len;i++)
    {
        string x=s.substr(i,len-i)+s.substr(0,i);
        if(x<tmp)
        {
            tmp=x;
            t=ans;
        }
        ans++;
    }

    cout<<t<<endl;
字符串s,tmp;
char-ss[100002];
scanf(“%s”,ss);
s=ss;
tmp=s;
int i,len=s.size(),ans=0,t=0;
对于(i=0;i你可以使用modified。我的意思是modified,因为你不能停在词尾

以下是一个I已解决的(SA是后缀数组)的代码:

/719
//玻璃珠
//杂项;字符串匹配;后缀数组;循环
#包括
#包括
#包括
#包括
#包括
#定义最大值10050
使用名称空间std;
int-RA[MAX],tempRA[MAX];
int-SA[MAX],tempSA[MAX];
int C[MAX];
无效后缀_排序(int n,int k){
memset(C,0,sizeof C);
对于(int i=0;i>tt;
而(tt--){
字符串s;cin>>s;
后缀_数组;

cout我知道这来得很晚,但我在搜索该算法更快的变体时,从谷歌那里偶然发现了这一点。事实证明,在github上找到了一个很好的实现:

它使用lyndon分解。这意味着它会重复地将字符串拆分为按字典顺序递减的lyndon单词。lyndon单词是自身最小旋转的字符串之一。以循环方式执行此操作会生成字符串的lms,作为最后找到的lyndon单词

int lyndon_word(const char *a, int n)
{
  int i = 0, j = 1, k;
  while (j < n) {
    // Invariant: i < j and indices in [0,j) \ i cannot be the first optimum
    for (k = 0; k < n && a[(i+k)%n] == a[(j+k)%n]; k++);
    if (a[(i+k)%n] <= a[(j+k)%n]) {
      // if k < n
      //   foreach p in [j,j+k], s_p > s_{p-(j-i)}
      //   => [j,j+k] are all suboptimal
      //   => indices in [0,j+k+1) \ i are suboptimal
      // else
      //   None of [j,j+k] is the first optimum
      j += k+1;
    } else {
      // foreach p in [i,i+k], s_p > s_{p+(j-i)}
      // => [i,i+k] are all suboptimal
      // => [0,j) and [0,i+k+1) are suboptimal
      // if i+k+1 < j
      //   j < j+1 and indices in [0,j+1) \ j are suboptimal
      // else
      //   i+k+1 < i+k+2 and indices in [0,i+k+2) \ (i+k+1) are suboptimal
      i += k+1;
      if (i < j)
        i = j++;
      else
        j = i+1;
    }
  }
  // j >= n => [0,n) \ i cannot be the first optimum
  return i;
}
int-lyndon\u单词(常量字符*a,int-n)
{
int i=0,j=1,k;
while(j[j,j+k]都是次优的
//=>在[0,j+k+1]中的索引是次优的
//否则
//[j,j+k]中没有一个是第一最优的
j+=k+1;
}否则{
//在[i,i+k],s_p>s_{p+(j-i)}
//=>[i,i+k]都是次优的
//=>[0,j)和[0,i+k+1)是次优的
//如果i+k+1=n=>[0,n)\n我不能是第一个最佳值
返回i;
}

请不要使用“否”和“plz”等地区缩写。StackOverflow拥有全球受众,其中许多人不是英语母语人士。此外,什么是TLE?“其他”优化?除了什么?您回答了错误的问题。链接的问题是轮换次数,而不是词典中最小的答案。@Robᵩ TLE是spoj中使用的首字母缩略词,意思是超过了时间限制。看起来OP需要加快他的解决方案。@Watusimoto:是的。我需要旋转的数量,但为此,我需要确定字典中最小的字符串是什么。我请你解释后缀数组的构造,或者给我一些解释其构造的链接。请请在此处明确快速实现的要点,而不仅仅是链接到它,这样,如果链接消失,答案仍然是答案。这样做更可取。@m69当然。我希望这个版本更好?但仍然是一个相当简短的解释。信息:此算法与“Shiloach的快速规范化算法”(Shiloach's Fast Canonization algorithm)的第2阶段相同。
int lyndon_word(const char *a, int n)
{
  int i = 0, j = 1, k;
  while (j < n) {
    // Invariant: i < j and indices in [0,j) \ i cannot be the first optimum
    for (k = 0; k < n && a[(i+k)%n] == a[(j+k)%n]; k++);
    if (a[(i+k)%n] <= a[(j+k)%n]) {
      // if k < n
      //   foreach p in [j,j+k], s_p > s_{p-(j-i)}
      //   => [j,j+k] are all suboptimal
      //   => indices in [0,j+k+1) \ i are suboptimal
      // else
      //   None of [j,j+k] is the first optimum
      j += k+1;
    } else {
      // foreach p in [i,i+k], s_p > s_{p+(j-i)}
      // => [i,i+k] are all suboptimal
      // => [0,j) and [0,i+k+1) are suboptimal
      // if i+k+1 < j
      //   j < j+1 and indices in [0,j+1) \ j are suboptimal
      // else
      //   i+k+1 < i+k+2 and indices in [0,i+k+2) \ (i+k+1) are suboptimal
      i += k+1;
      if (i < j)
        i = j++;
      else
        j = i+1;
    }
  }
  // j >= n => [0,n) \ i cannot be the first optimum
  return i;
}