数组开小毁一生……

题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2085

这题在洛谷上有个条件是“互不包含”,其实bzoj的数据也满足这个条件,否则我目前已知的所有做法都是错的。

个人觉得AC自动机可以用其他办法做,但是没试过

KMP(或者hash), \(f[i][j]\)表示\(i\)完了接上\(j\)需要多少个字符,直接用KMP求出最长的同时是\(j\)串的前缀和\(i\)串的后缀的串即可

然后求走\((m-1)\)步的最短路,倍增Floyd

并不是多串匹配一定要用AC自动机!即使不考虑正确性,AC自动机的Trie树在复杂度上可能还多个字符集大小,不一定比KMP快,一定要合理选择!

代码

KMP:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define llong long long
using namespace std;const int N = 200;
const int S = 26;
const int L = 1e5+1e3;
const int LGM = 30;
const llong INF = 1e17;
llong f[N+3][N+3],g[N+3][N+3],g0[N+3][N+3];
char a[L+3];
int nxt[L+3];
int len[L+3];
int slen[L+3];
int n; llong m;void update(llong &x,llong y) {x = min(x,y);}int KMP(char str1[],char str2[],int len1,int len2)
{for(int i=0; i<=len1; i++) nxt[i] = 0;for(int i=2; i<=len1; i++){nxt[i] = nxt[i-1];while(nxt[i]!=0 && str1[i]!=str1[nxt[i]+1]){nxt[i] = nxt[nxt[i]];}if(str1[i]==str1[nxt[i]+1]) nxt[i]++;}if(str1==str2){return len1-nxt[len1];}else{int j = 0;for(int i=1; i<=len2; i++){while(j && str1[j+1]!=str2[i]){j = nxt[j];}if(j<len1 && str1[j+1]==str2[i]) j++;}return len1-j;}
}int main()
{scanf("%d%lld",&n,&m);for(int i=1; i<=n; i++){scanf("%s",a+slen[i-1]+1); len[i] = strlen(a+slen[i-1]+1); slen[i] = slen[i-1]+len[i]+1; a[slen[i]] = ' ';}for(int i=1; i<=n; i++) {for(int j=1; j<=n; j++) {f[i][j] = g0[i][j] = g[i][j] = INF;}}for(int i=1; i<=n; i++) f[i][i] = len[i];for(int i=1; i<=n; i++){for(int j=1; j<=n; j++){g0[j][i] = KMP(a+slen[i-1],a+slen[j-1],len[i],len[j]);}}/*for(int i=1; i<=n; i++){for(int j=1; j<=n; j++){printf("g0: %d %d %lld\n",i,j,g0[i][j]);}}*/m--;while(m>0){if(m&1){for(int k=1; k<=n; k++){for(int i=1; i<=n; i++){for(int j=1; j<=n; j++){update(g[i][j],f[i][k]+g0[k][j]);}}}for(int i=1; i<=n; i++){for(int j=1; j<=n; j++){f[i][j] = g[i][j];g[i][j] = INF;}}}for(int k=1; k<=n; k++){for(int i=1; i<=n; i++){for(int j=1; j<=n; j++){update(g[i][j],g0[i][k]+g0[k][j]);}}}for(int i=1; i<=n; i++){for(int j=1; j<=n; j++){g0[i][j] = g[i][j];g[i][j] = INF;}}m>>=1;}llong ans = INF;for(int i=1; i<=n; i++){for(int j=1; j<=n; j++){ans = min(ans,f[i][j]);}}printf("%lld\n",ans);return 0;
}

AC自动机WA+TLE代码

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#define llong long long
using namespace std;const int N = 200;
const int S = 26;
const int L = 1e5+1;
const int LGM = 30;
const llong INF = 1e17;
void update(llong &x,llong y) {x = min(x,y);}
llong g0[N+3][N+3],g[N+3][N+3],f[N+3][N+3];
int len[N+3];
int fail[L+3];
int son[L+3][S+3];
int idpos[N+3];
char a[L+3];
int id[L+3];
int que[L+3];
int dep[L+3];
int n,rtn,siz; llong m;void insertstr(char str[],int sid)
{int u = rtn;for(int i=1; i<=len[sid]; i++){if(son[u][str[i]]){u = son[u][str[i]];}else{siz++; son[u][str[i]] = siz;u = siz;}}id[u] = sid;idpos[sid] = u;
}void add(int u,int v,llong w)
{update(g0[id[u]][id[v]],w);
}void getfail()
{int head = 1,tail = 0;for(int i=1; i<=S; i++){int v = son[rtn][i];if(v){tail++; que[tail] = v;fail[v] = rtn;}}while(head<=tail){int u = que[head]; head++;for(int i=1; i<=S; i++){int v = son[u][i];if(v) {fail[son[u][i]] = son[fail[u]][i]; tail++; que[tail] = v;}else {son[u][i] = son[fail[u]][i];}}}
}void bfs(int s)
{printf("bfs(%d)\n",s);for(int i=1; i<=siz; i++) dep[i] = 0;int head = 1,tail = 1; que[1] = s;while(head<=tail){int u = que[head]; head++;int v = fail[i];for(int i=1; i<=S; i++){v = son[u][i];if(v && dep[v]==0){dep[v] = dep[u]+1;add(s,v,dep[v]);tail++; que[tail] = v;}}}
}int main()
{scanf("%d%lld",&n,&m); rtn = siz = 0;for(int i=1; i<=n; i++){scanf("%s",a+1); len[i] = strlen(a+1);for(int j=1; j<=len[i]; j++) a[j] -= 96;insertstr(a,i);}getfail();for(int i=0; i<=siz; i++) printf("AC%d fail%d\n",i,fail[i]);for(int i=0; i<=siz; i++) {for(int j=1; j<=S; j++) {if(son[i][j]) {printf("son[%d][%c]=%d\n",i,j+96,son[i][j]);}}}for(int i=1; i<=n; i++) {for(int j=1; j<=n; j++) {f[i][j] = g0[i][j] = g[i][j] = INF;}}for(int i=1; i<=n; i++) f[i][i] = 0ll;for(int i=1; i<=siz; i++){if(id[i]){bfs(i);}}/*for(int i=1; i<=n; i++){for(int j=1; j<=n; j++){printf("g0: %d %d %lld\n",i,j,g0[i][j]);}}*/m--;while(m>0){if(m&1){for(int k=1; k<=n; k++){for(int i=1; i<=n; i++){for(int j=1; j<=n; j++){update(g[i][j],f[i][k]+g0[k][j]);}}}for(int i=1; i<=n; i++){for(int j=1; j<=n; j++){f[i][j] = g[i][j];g[i][j] = INF;}}}for(int k=1; k<=n; k++){for(int i=1; i<=n; i++){for(int j=1; j<=n; j++){update(g[i][j],g0[i][k]+g0[k][j]);}}}for(int i=1; i<=n; i++){for(int j=1; j<=n; j++){g0[i][j] = g[i][j];g[i][j] = INF;}}m>>=1;}llong ans = INF;for(int i=1; i<=n; i++){for(int j=1; j<=n; j++){ans = min(ans,len[i]+f[i][j]);}}printf("%lld\n",ans);return 0;
}
/*
4 11
aaaaaaa
aaaa
aaaaaa
aaaaaaaaaa
*/

BZOJ 2085 luogu P3502 [POI2010]Hamsters (KMP、Floyd、倍增)相关推荐

  1. bzoj2085 [Poi2010]Hamsters 哈希+倍增

    Description Tz养了一群仓鼠,他们都有英文小写的名字,现在Tz想用一个字母序列来表示他们的名字,只要他们的名字是字母序列中的一个子串就算,出现多次可以重复计算.现在Tz想好了要出现多少个名 ...

  2. UOJ #219 BZOJ 4650 luogu P1117 [NOI2016]优秀的拆分 (后缀数组、ST表)

    UOJ #219 BZOJ 4650 luogu P1117 [NOI2016]优秀的拆分 (后缀数组.ST表) 连NOI Day1T1都不会做...看了题解都写不出来还要抄Claris的代码.. 题 ...

  3. UOJ #131 BZOJ 4199 luogu P2178【NOI2015】品酒大会 (后缀自动机、树形DP)

    UOJ #131 BZOJ 4199 luogu P2178[NOI2015]品酒大会 (后缀自动机.树形DP) 水是水,但是写出了不少问题,因此写一发博客. https://www.luogu.or ...

  4. BZOJ 1500 Luogu P2042 [NOI2005] 维护数列 (Splay)

    BZOJ 1500 Luogu P2042 [NOI2005] 维护数列 (Splay) 手动博客搬家: 本文发表于20180825 00:34:49, 原地址https://blog.csdn.ne ...

  5. BZOJ 3930 Luogu P3172 选数 (莫比乌斯反演)

    BZOJ 3930 Luogu P3172 选数 (莫比乌斯反演) 手动博客搬家:本文发表于20180310 11:46:11, 原地址https://blog.csdn.net/suncongbo/ ...

  6. POJ 1061 BZOJ 1477 Luogu P1516 青蛙的约会 (扩展欧几里得算法)

    POJ 1061 BZOJ 1477 Luogu P1516 青蛙的约会 (扩展欧几里得算法) 手动博客搬家: 本文发表于20180226 23:35:26, 原地址https://blog.csdn ...

  7. BZOJ 1101 Luogu P3455 POI 2007 Zap (莫比乌斯反演+数论分块)

    BZOJ 1101 Luogu P3455 POI 2007 Zap (莫比乌斯反演+数论分块) 手动博客搬家: 本文发表于20171216 13:34:20, 原地址https://blog.csd ...

  8. BZOJ 2152 Luogu 2634——聪聪可可

    BZOJ 2152  Luogu 2634--聪聪可可 题意 求两点之间路径和为3的倍数占的概率(最简) 解题思路与BZOJ1468差不多, 不过本题在计算经过某个点的次数时用了个ans数组, 对路径 ...

  9. BZOJ 2085 [Poi2010]Hamsters Hash+倍增floyd

    题意:链接 方法: Hash+倍增floyd 解析: 首先这个BZ的无脑翻译我真是受不了. 加俩条件 所有串的长度总和不超过100000,并且对于任意不同子串A,B,A不包含于B,B不包含于A. 然后 ...

最新文章

  1. 独家 | 使用高斯混合模型,让聚类更好更精确(附数据代码学习资源)
  2. linux仿mac os10,Win10就是不如Mac顺手?几款仿Mac小工具推荐
  3. Linux下Verilog仿真过程(二)
  4. JQuery 中选择多选择框,和单选框,实现获取相应选择的值
  5. bowtie1和bowtie2的比较
  6. localdate存mysql相差一天_如何在保存到mySQL数据库时阻止LocalDate更改
  7. 【android原生态RPG游戏框架源码】
  8. 和为S的两个数字(python)
  9. 计算机专业大学排名_2020全国计算机专业大学排名
  10. astrolog php,如何在苹果MAC上使用Astrolog32 zet9等占星软件
  11. oracle数据库中视图是什么,orcl数据库视图是什么
  12. 如何开发手机商城app? 商城APP功能
  13. udp通信2--多发多收
  14. Nature Medicine 揭示冠状动脉疾病的个体危险因素
  15. hibernate学习(4)——实体配置详解
  16. android流程点击开机键熄屏,一种基于android系统的灭屏状态下指纹解锁加速亮屏方法与流程...
  17. Axhub Charts学习记录贴-条形图添加正序排序/倒序排序功能
  18. 计算机毕业设计Java游泳馆管理平台(系统+程序+mysql数据库+Lw文档)
  19. 收割大厂offer需要具备的条件
  20. 2020前端面试题72道总结

热门文章

  1. 龙族幻想东京机器人一次_龙族幻想凌晨四点的东京机器人位置在哪?
  2. Android各种访问权限Permission详解
  3. pcie equalization学习笔记后续再整理
  4. 百度首页关于小米的新闻? 百度百家会不会成为百度败家
  5. PersistenceUnit、PersistenceContext
  6. 学习笔记 - CFA 衍生品 2
  7. 学习笔记 - CFA 固收 2
  8. vue element Dialog 蒙板的覆盖页面
  9. MyBatis:延时加载
  10. B树的插入、删除操作