新疆省赛A.A. chino with string(AC自动机+广义矩阵快速幂)
前置知识:
[TJOI2012]可乐
广义矩阵快速幂
AC自动机
#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
typedef long long ll;
int nxt[maxn][26],fail[maxn];
ll c[maxn];
int tot=1,rt=1,n,m;
void ins (string s,int x) {
int u=rt;
for (char i:s) {
if (!nxt[u][i-'a']) nxt[u][i-'a']=++tot;
u=nxt[u][i-'a'];
}
c[u]+=x;
}
void build () {
queue<int> q;
fail[rt]=rt;
for (int i=0;i<26;i++) {
if (!nxt[rt][i]) nxt[rt][i]=rt;
else {
fail[nxt[rt][i]]=rt;
q.push(nxt[rt][i]);
}
}
while (q.size()) {
int u=q.front();
q.pop();
for (int i=0;i<26;i++) {
if (!nxt[u][i]) {
nxt[u][i]=nxt[fail[u]][i];
}
else {
fail[nxt[u][i]]=nxt[fail[u]][i];
q.push(nxt[u][i]);
}
}
}
}
vector<int> g[maxn];
ll cc[maxn];
void dfs (int u,ll sum) {
cc[u]=sum;
for (int v:g[u]) {
dfs(v,sum+c[v]);
}
}
struct matrix {
ll m[205][205];
}ans,base;
matrix mul (matrix a,matrix b) {
matrix ans;
for (int i=1;i<=tot;i++) for (int j=1;j<=tot;j++) ans.m[i][j]=-1e18;
// for (int i=1;i<=tot;i++) for (int j=1;j<=tot;j++) {
// ans.m[i][j]=max(a.m[i][j],b.m[i][j]);
// }
for (int k=1;k<=tot;k++) {
for (int i=1;i<=tot;i++) {
for (int j=1;j<=tot;j++) {
if (a.m[i][k]!=-1e18&&b.m[k][j]!=-1e18)
ans.m[i][j]=max(ans.m[i][j],a.m[i][k]+b.m[k][j]);
}
}
}
return ans;
}
void qpow (int p) {
while (p) {
if (p&1) ans=mul(ans,base);
base=mul(base,base);
p>>=1;
}
}
/*
17 3
helloworld 100
ldldl 5
aaa -6
*/
int main () {
cin>>n>>m;
for (int i=1;i<=m;i++) {
string s;
int x;
cin>>s>>x;
ins(s,x);
}
build();
for (int i=2;i<=tot;i++) g[fail[i]].push_back(i);
dfs(1,c[1]);
//for (int i=1;i<=tot;i++) printf("%d ",cc[i]);
//puts("");
for (int i=1;i<=tot;i++) for (int j=1;j<=tot;j++) {
base.m[i][j]=-1e18;
}
for (int i=1;i<=tot;i++) {
for (int j=0;j<26;j++) {
base.m[i][nxt[i][j]]=cc[nxt[i][j]];
}
}
ans=base;
// for (int i=1;i<=tot;i++) {
// for (int j=1;j<=tot;j++) printf("%lld ",base.m[i][j]);
// puts("");
// }
//n=1;
//n=17;
qpow(n-1);
long long Ans=-1e18;
for (int i=1;i<=tot;i++) {
Ans=max(Ans,ans.m[1][i]);
//printf("%lld ",ans.m[1][i]);
}
printf("%lld\n",Ans);
}