link:http://acm.hdu.edu.cn/showproblem.php?pid=6761
建议学习该博客:https://blog.csdn.net/wayne_lee_lwc/article/details/107528945 √
AC代码:(基本搬运...看了半天才懂了一点点...还要好好深入理解)
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<iomanip>
#include<cstdio>
#include<string>
#define ll long long
using namespace std;
const int maxn = 2e7+10;
const int m = 1e9+7;
int n;
int pos[maxn];//记录以i为结尾的前缀串中,字典序最小的后缀的首字符的下标
char s[maxn];
void lyndon_duval()
{
int i = 0,j,k;//i j k
while(i < n){
k = i;
j = i + 1;
//凡是与pos数组有关的下标皆需改动
while(j < n && s[j] >= s[k]){
if(s[j] == s[k]){
pos[j] = pos[k] + j - k;
k++;
}else{
k = i;
pos[j] = i + 1;//此时为完整的lyndon串
}
j++;
}
while(i <= k){
i += j - k;
}
if(i == j && i < n){
pos[j] = i + 1;//完全分解の特判
}
}
}
void cal_out()
{
ll ans = 0;
for (int i = n - 1; i >= 0; i--) ans = (1112LL * ans + pos[i]) % m;//qjs
cout << ans << endl;
}
int main(){
int T;cin >> T;
while( T-- ){
scanf("
");//略略略
cin >> s;
n = strlen(s);//
pos[0] = 1;
lyndon_duval();
cal_out();
}
//慎用memset!//本来想保险一点memset一波,结果超时...
return 0;
}