watashi大神的代码
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
vector<int> pos(const string& s, const string& p) {
vector<int> ret;
for (string::size_type i = s.find(p); i != string::npos; i = s.find(p, i + 1)) {
ret.push_back(i);
}
return ret;
}
int main() {
string str, prefix, suffix;
vector<int> begin, end;
vector<unsigned long long> hash;
cin >> str >> prefix >> suffix;
begin = pos(str, prefix);
end = pos(str, suffix);
for (int i: begin) {
int k = i;
unsigned long long code = 0;
for (int j: end) {
if (i <= j && i + (int)prefix.length() <= j + (int)suffix.length()) { //i和j分别是前缀和后缀开始位置
while (k < j + (int)suffix.length()) { //i处前缀和j处后缀能够组成字符串条件是i<=j && i+前缀长度<=j+后缀长度
code = code * 29 + str[k++];
}
hash.push_back(code);
}
}
}
sort(hash.begin(), hash.end());
printf("%d\n", unique(hash.begin(), hash.end()) - hash.begin());
return 0;
}
CF196D 求字典序最小的最大回文字串长度不超过d的串
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define P 1000000007
using namespace std;
typedef unsigned long long ull;
char str[400100];
int d,len;
ull p[400100];
ull r[400100],l[400100];
char ans[400100];
bool dfs(int pos,int doing){
if(pos==len)return 1;
char s;
if(doing)s=str[pos];
else s='a';
for(;s<='z';s++){
r[pos+1]=P*r[pos]+s;
l[pos+1]=l[pos]+p[pos]*s;
ans[pos]=s;
if(pos+1>=d){
if(((r[pos+1]-r[pos+1-d]*p[d])*p[pos+1-d])==(l[pos+1]-l[pos+1-d])) //
continue;
}
if(pos+1>=d+1){
if(((r[pos+1]-r[pos-d]*p[d+1])*p[pos-d])==(l[pos+1]-l[pos-d])) //这两处公式一定要对
continue;
}
bool flag=0;
if(doing && s==str[pos]) //注意这里是str[pos]
flag=dfs(pos+1,1);
else
flag=dfs(pos+1,0);
if(flag)
return 1 ;
}
return 0;
}
int main(){
int i;
scanf("%d%s",&d,str);
len=strlen(str);
for(i=len-1;i>=0&&str[i]=='z';i--) str[i]='a';
if(i<0) return puts("Impossible"),0;
str[i]++; //注意要找到它的下一个字符串
p[0]=1;
for(i=1;i<400100;i++) //注意小于号
p[i]=p[i-1]*P;
r[0]=l[0]=0;
if(dfs(0,1)){
ans[len]='\0';
printf("%s\n",ans);
}
else
printf("Impossible\n");
return 0;
}