https://vjudge.net/contest/189927#problem/M
题意:字符串的第一个会变到最后一个,之后有一个顺序,第一次变化是第一名,第二次变化是第二名,然后问你字典序最小和字典序最大的串在第几名,它出现的次数是多少
思路:出现的次数好算,因为一个串出现的次数就是len/(len-nex[len])吗,现在就是看他是第几位比较难,其实也不难就是看一个字符在字符串中的大
#include <stdio.h>
#include <iostream>
#include <string.h>
using namespace std;
const int maxn = 1e6+10;
char ch[maxn];
int nex[maxn],cnt[26];
void pre_kmp(char str[])
{
memset(nex,0,sizeof(nex));
int len = strlen(str) , i = 0 , k = -1;
nex[0] = -1;
while( i < len )
{
if( k == -1 || str[i] == str[k])
{
i++,k++;
nex[i] = k;
}
else
{
k = nex[k];
}
}
}
int Min_MAX(char str[],int flag)
{
int i = 0 , j = 1 , k = 0;
int len = strlen(str);
while( i<len && j<len && k<len )
{
// puts("-----\n");
int t = str[(j + k)%len] - str[(i+k)%len];
if(t == 0)
{
k++;
}
else
{
if(flag)
{
if(t<0)
{
i+= k+1;
}
else
{
j+= k+1;
}
}
else
{
if(t<0)
{
j+= k+1;
}
else
{
i+= k +1;
}
}
if(i == j) j++;
k = 0;
}
}
return min(i,j);
}
int main()
{
while(scanf("%s",ch)!=EOF)
{
memset( cnt , 0 , sizeof(cnt) );
pre_kmp(ch);
int len = strlen(ch);
int ans;
if( len % (len - nex[len]) ==0 ) ans = len / (len - nex[len]);
else ans = 1;
int s = Min_MAX(ch,1);
int e = Min_MAX(ch,0);
printf("%d %d %d %d\n",s+1,ans,e+1,ans);
}
}
小位置就好了,这里就用到最大最小表示法,(表示自己并不是很会用= =。。过几天在在写一篇吧)上代码: