题目:
http://acm.csu.edu.cn:20080/csuoj/problemset/problem?pid=2294
http://codeforces.com/gym/101158/attachments
题意:
给出两个字符串,长度小于4000,求一个最长的"nb的公共子串"."nb的公共子串"的定义是两个子串中出现的每个字符个数相同.
思路:
前缀和处理区间内字符个数.
枚举同一长度的所有的子串,将子串中每个字符出现的个数储存在一个26进制的每一位中.
可以证明, 同长度的不是"nb的公共子串"的串不会有相同的值[1].
那么只需要枚举长度, 枚举所有同长度子串, 将其对应的数存入unordered_map,枚举检查两个map中有无相同数即可. 复杂度.
[1]:buzhidaoyayingyingying
#include<bits/stdc++.h>
#define fuck(x) std::cout<<"["<<#x<<"->"<<x<<"]"<<endl;
using namespace std;
typedef unsigned long long ll;
char x[4005];
char y[4005];
int presum1[4005][26];
int presum2[4005][26];
unordered_map<ll,int>mp1,mp2;
int main() {
scanf("%s",x);
scanf("%s",y);
int len1=strlen(x),len2=strlen(y);
int len=min(len1,len2);
memset(presum1,0,sizeof(presum1));
memset(presum2,0,sizeof(presum2));
for(int i=0; i<len1; i++) {
for(int j=0; j<26; j++) {
presum1[i+1][j]=presum1[i][j];
}
presum1[i+1][x[i]-'a']=presum1[i][x[i]-'a']+1;
}
for(int i=0; i<len2; i++) {
for(int j=0; j<26; j++) {
presum2[i+1][j]=presum2[i][j];
}
presum2[i+1][y[i]-'a']=presum2[i][y[i]-'a']+1;
}
int ans=0;
for(int i=len; i>0; i--) {
mp1.clear();
mp2.clear();
for(int j=0; j+i<=len1; j++) {
ll sum=0;
ll mul=1;
for(int k=0; k<26; k++) {
sum+=(presum1[j+i][k]-presum1[j][k])*mul;
mul*=26;
}
mp1[sum]=1;
}
for(int j=0; j+i<=len2; j++) {
ll sum=0;
ll mul=1;
for(int k=0; k<26; k++) {
sum+=(presum2[j+i][k]-presum2[j][k])*mul;
mul*=26;
}
mp2[sum]=1;
}
for(auto xxx:mp1) {
if(mp2.count(xxx.first)) {
ans=i;
break;
}
}
if(ans!=0)
break;
}
printf("%d\n",ans);
return 0;
}