【JZOJ4910】【NOIP2017模拟12.3】子串
2016-12-03 16:09
330 查看
题目描述
数据范围
=w=
暴力:从前往后枚举一个i,再从前往后枚举一个j:
如果s[i]不是s[j]的子串,更新答案,继续枚举;
如果s[i]是s[j]的子串,停止枚举。
因为对于s[k] (k>j),s[i]如果不是s[k]的子串,那么s[j]也不是s[k]的子串。
代码
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> #define ll long long using namespace std; const char* fin="sub.in"; const char* fout="sub.out"; const int inf=0x7fffffff; const int maxn=507,maxlen=2007; int t,n,i,j,k,p,ans; char s[maxn][maxlen]; int len[maxn],fail[maxn][maxlen]; bool judge(int a,int b){ int i,j,k,p=0; for (i=1;i<=len[b];i++){ while (p && s[a][p+1]!=s[b][i]) p=fail[a][p]; if (s[a][p+1]==s[b][i]) p++; if (p==len[a]) return true; } return false; } int main(){ freopen(fin,"r",stdin); freopen(fout,"w",stdout); scanf("%d",&t); while (t--){ scanf("%d",&n); for (i=1;i<=n;i++) scanf("%s",s[i]+1); for (i=1;i<=n;i++){ len[i]=strlen(s[i]+1); p=0; for (j=2;j<=len[i];j++){ while (p && s[i][p+1]!=s[i][j]) p=fail[i][p]; if (s[i][p+1]==s[i][j]) p++; fail[i][j]=p; } } ans=0; for (i=1;i<=n;i++){ for (j=max(ans,i+1);j<=n;j++) if (judge(i,j)) break; else ans=j; } if (ans) printf("%d\n",ans); else printf("-1\n"); } return 0; }
=o=
我的暴力和正解的区别:正解:枚举i,然后处理所有i对其他人的贡献①;
我:枚举i,然后处理所有其他人对i的贡献②。
两种都显然正确;
但是区别是有的,前者可能会更容易优化。
类比动态规划:
对于两个等价的方程:
f[1..i−1]⇒f[i],以及f[i−1]⇒f[i]。
显然后者更容易优化,栗子。
这个由于算的顺序不同导致我走远的栗子不唯一。
这道题当时我算的方式跟正解不同,然后我化简化得很困难。
以后大概两种搜索方式都尝试一下吧。
相关文章推荐
- JZOJ 4910. 【NOIP2017模拟12.3】子串
- 【NOIP2017模拟12.3】子串
- JZOJ 4910. 【NOIP2017模拟12.3】子串
- 【NOIP2017模拟12.3】子串
- JZOJ 4909 【NOIP2017模拟12.3】李龟下棋
- JZOJ 4909. 【NOIP2017模拟12.3】李电下棋
- JZOJ 4911. 【NOIP2017模拟12.3】人生的叹息
- JZOJ 4911 【NOIP2017模拟12.3】人生的叹息
- 【NOIP2017模拟12.3】和【12.10】总结
- NOIP2017 赛前模拟(2017.10.30)考试总结
- (前缀和排序)NOIP2017提高组模拟 Day1P1 小A的数学
- NOIP2017提高组模拟22-雅礼国庆10.5
- 【NOIP2017提高组模拟12.10】幻魔皇
- JZOJ.5279【NOIP2017模拟8.15】香港记者
- 【NOIP2017提高组A组模拟8.17】行程的交集
- JZOJ.5305【NOIP2017模拟8.18】C
- JZOJ.5287【NOIP2017模拟8.16】最短路
- 【NOIP2017模拟9.3A组】摘果子
- 4774. 【GDOI2017模拟9.10】子串
- 【NOIP2017提高A组模拟10.5】Ping