题目:CodeForces196-D:The Next Good String
题意:给定仅由小写字母组成的字符串S和一个正整数m。求一个长度与S相同的仅由小写字母组成的字符串S1,满足:
- S1>S
- S1中不含长度大于等于d的回文串。
思路:许昊然的文章里叫“逐位确定法”,以为之前没见到过官方名字,就姑且这样叫了。具体如下。
一: 预处理得到大于等于字符串S的最小字典序新串S’:
- 最后面的连续的‘z‘全部改为‘a’。 因为肯定前面有以为要改,所以后面的越小越好。
- 把从后向前扫描的第一位非‘z’位++。
二: 根据上面两步得到了大于字符串S的最小字典序新串S’,然后dfs,得到满足条件的最小字典序新串S1。
此题具体实现:
1,题意等效于不存在长度位d和d+1的回文串。
2,检查回文串的时候用hash判定即可。
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std; #define ull unsigned long long const int maxn=1000000; const int seed=131; ull g[maxn],hash1[maxn],hash2[maxn]; int N,M; char c[maxn],ans[maxn]; bool palindrome(int L,int R) { if(L<=0) return false; if(hash2[R]-hash2[L-1]==(hash1[R]-hash1[L-1]*g[R-L+1])*g[L-1]) return true; return false; } bool dfs(int pos,int ismax) { if(pos==N+1) { puts(ans+1); return true; } for(ans[pos]=ismax?c[pos]:‘a‘;ans[pos]<=‘z‘;ans[pos]++){ hash1[pos]=hash1[pos-1]*seed+ans[pos]; hash2[pos]=hash2[pos-1]+ans[pos]*g[pos-1]; if(!palindrome(pos-M+1,pos)&&!palindrome(pos-M,pos)&&dfs(pos+1,ismax&&ans[pos]==c[pos])) return true; } return false; } int main() { int i; scanf("%d%s",&M,c+1); N=strlen(c+1); for(i=N;i>=1&&c[i]==‘z‘;i--) c[i]=‘a‘; if(i<=0) { puts("Impossible"); return 0; } c[i]++; g[0]=1; for(i=1;i<=N;i++) g[i]=g[i-1]*seed; if(!dfs(1,1)) puts("Impossible"); return 0; }