题目
题解
以后字符串的题就都打暴力了
后缀数组
多个串的最长公共子串
只要有n个>=len的height且其首字母属于不同的串就可以了
代码
后缀数组
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
#define Big (1000000000 + 10)
#define maxn 111111
using namespace std;
int sa[maxn],rk[maxn],b[maxn],c[maxn],x[maxn],y[maxn];
int height[maxn],stack[maxn],id[maxn],len[1010],a[1010][1010];
int num,cnt,n,m,l,r,maxx,minn,ans,top;
bool vis[maxn];
int read() {
char c=getchar();
int r=0,f=1;
while (!isdigit(c)) {
if (c=='-') f=-1;
c=getchar();
}
while (isdigit(c)) {
r=(r*10)+(c^48);
c=getchar();
}
return r*f;
}
int min(int x,int y) {
return x<y?x:y;}
int max(int x,int y) {
return x>y?x:y;}
void Get_SA() {
for (int i=1;i<=n;i++) ++c[x[i]=b[i]];
for (int i=2;i<=m;i++) c[i]+=c[i-1];
for (int i=n;i>=1;i--) sa[c[x[i]]--]=i;
for (int k=1;k<=n;k<<=1) {
cnt=0;
for (int i=n-k+1;i<=n;i++) y[++cnt]=i;
for (int i=1;i<=n;i++) if (sa[i]>k) y[++cnt]=sa[i]-k;
for (int i=1;i<=m;i++) c[i]=0;
for (int i=1;i<=n;i++) ++c[x[i]];
for (int i=2;i<=m;i++) c[i]+=c[i-1];
for (int i=n;i>=1;i--) sa[c[x[y[i]]]--]=y[i],y[i]=0;
swap(x,y);
x[sa[1]]=1; cnt=1;
for (int i=2;i<=n;i++)
x[sa[i]]=(y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k])?cnt:++cnt;
if (cnt==n) break;
m=cnt;
}
}
void Get_Height() {
int k=0;
for (int i=1;i<=n;i++) rk[sa[i]]=i;
for (int i=1;i<=n;i++) {
if (rk[i]==1) continue;
if (k) --k;
int j=sa[rk[i]-1];
while (j+k<=n && i+k<=n && b[i+k]==b[j+k]) ++k;
height[rk[i]]=k;
}
}
bool check(int x) {
while (top) vis[stack[top--]]=0;
for (int i=1;i<=n;i++) {
if (height[i]<x) {
while (top) vis[stack[top--]]=0;
}
if (!vis[id[sa[i]]]) {
vis[id[sa[i]]]=1;
stack[++top]=id[sa[i]];
if (top==num) return 1;
}
}
return 0;
}
int main() {
num=read();
l=0;r=minn=Big;
for (int i=1;i<=num;i++) {
len[i]=read();
for (int j=1;j<=len[i];j++) {
a[i][j]=read();
if (j!=1) maxx=max(maxx,a[i][j]-a[i][j-1]);
}
r=min(r,len[i]-1);
}
for (int i=1;i<=num;i++) {
for (int j=2;j<=len[i];j++) {
b[++n]=a[i][j]-a[i][j-1];
id[n]=i;
minn=min(minn,b[n]);
}
b[++n]=++maxx;
}
for (int i=1;i<=n;i++) {
b[i]=b[i]-minn+1;
m=max(m,b[i]);
}
Get_SA();
Get_Height();
while (l<=r) {
int mid=(l+r)>>1;
if (check(mid)) {
l=mid+1;
ans=mid;
}
else r=mid-1;
}
printf("%d",ans+1);
}
暴力:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=200100;//点数
int n,m,ans=0;
struct Xian{
int len,v[1001];
}a[1001];
int read()
{
char ch=getchar(); int now=0,f=1;
while (ch<'0' || ch>'9') {ch=getchar(); if (ch=='-') f=-1;}
while (ch>='0'&&ch<='9')
{
now=(now<<1)+(now<<3)+ch-'0';
ch=getchar();
}
return now*f;
}
int main()
{
// freopen("card.in","r",stdin);
// freopen("card.out","w",stdout);
n=read();
for (int i=1; i<=n; i++)
{
a[i].len=read();
for (int j=1; j<=a[i].len; j++) a[i].v[j]=read();
}
for (int i=1; i<=n; i++)
{
a[i].len--;
if (a[i].len==0) {
printf("1"); return 0;}
for (int j=1; j<=a[i].len; j++) a[i].v[j]=a[i].v[j+1]-a[i].v[j];
}
int ans=0;
for (int l=1; l<=a[1].len; l++)
{
int r=a[1].len;
for (int i=2; i<=n; i++)
{
int mx=0;
for (int j=1; j<=a[i].len; j++)
if (a[i].v[j]==a[1].v[l])
{
int p=j , now=l;
while (a[i].v[p]==a[1].v[now] && p<=a[i].len && now<=r)
{p++; now++;}
mx=max(mx,now-1);
}
r=min(r,mx);
}
ans=max(ans,r-l+1);
}
printf("%d",ans+1);//输出长度+1
return 0;
}
总结
一种常见的处理方式:把多个串链接成一个串,中间加上一些符号