poj3167 Cow Patterns KMP、树状数组
来源:互联网 发布:luxsens 人工智能 编辑:程序博客网 时间:2024/06/05 19:26
最近的日子被考试压得喘不过气来,说好的每天水两道题又荒废了。。。
为了让写解题报告和看解题报告不那么无聊,我决定从这篇起每篇加几句心得或感慨(很大几率是废话):
数据结构是好东西,必须信手拈来,或者准备好模块,熟练得像std::sort那样,才能克服一些稍显复杂的堆砌算法的题目。
另外,KMP是神奇的算法。
poj3167
KMP&树状数组。
这题要求第一串中间是否有与第二串的匹配的子串。只不过匹配方式改成了只要大小关系相同就算可匹配。
思考后,有个重要的结论:
当某一段s1[i..j]与s2[k..l]可以匹配,那么对于s1[i..j+1]与s2[k..l+1]是否能匹配的充要条件是:
s1[i..j]中小于s1[j+1]的数和s2[k..l]中小于s2[l+1]的数个数相同,等于的个数也相同(那么大于的个数自然也相同)。
有了这个结论,就可以通过修改KMP算法求出匹配串了。
具体就是通过树状数组统计s1[i..j],s2[k..l]中小于和等于的数的个数就可以了。这题的S范围很小,暴力也应该可以。
为了让写解题报告和看解题报告不那么无聊,我决定从这篇起每篇加几句心得或感慨(很大几率是废话):
数据结构是好东西,必须信手拈来,或者准备好模块,熟练得像std::sort那样,才能克服一些稍显复杂的堆砌算法的题目。
另外,KMP是神奇的算法。
poj3167
KMP&树状数组。
这题要求第一串中间是否有与第二串的匹配的子串。只不过匹配方式改成了只要大小关系相同就算可匹配。
思考后,有个重要的结论:
当某一段s1[i..j]与s2[k..l]可以匹配,那么对于s1[i..j+1]与s2[k..l+1]是否能匹配的充要条件是:
s1[i..j]中小于s1[j+1]的数和s2[k..l]中小于s2[l+1]的数个数相同,等于的个数也相同(那么大于的个数自然也相同)。
有了这个结论,就可以通过修改KMP算法求出匹配串了。
具体就是通过树状数组统计s1[i..j],s2[k..l]中小于和等于的数的个数就可以了。这题的S范围很小,暴力也应该可以。
#include<cstdio>#include<cstring>using namespace std;#define lowbit(x) (x&(-x))#define NN 101000int c1[NN],c2[NN],next[NN],s,ans[NN];char s1[NN],s2[NN];void update(int c[],int x,int val){ while(x<=s){ c[x]+=val; x+=lowbit(x); }}int query(int c[],int x){ int ret=0; while(x){ ret+=c[x]; x-=lowbit(x); } return ret;}void getnext(int next[],char s2[],int l2){ int i=0,j=-1; int tail=1; memset(c1,0,sizeof(c1)); memset(c2,0,sizeof(c2)); next[i]=j; while(i<l2){ if ( j<0|| (query(c2,s2[j]-1)==query(c1,s2[i]-1) && query(c2,s2[j])==query(c1,s2[i])) ) { if (j>-1) update(c2,s2[j],1); if (i>0) update(c1,s2[i],1); i++;j++;next[i]=j; } else { int k=j-1; j=next[j]; for(k;k>=j;k--) {if (k<0) break;update(c2,s2[k],-1);} int tt=i-j; for(tail;tail<tt;tail++) update(c1,s2[tail],-1); } }}int KMP(char s1[],char s2[],int l1,int l2,int next[]){ int i,j; int cnt=0; int tail=0; i=j=-1; memset(c1,0,sizeof(c1)); memset(c2,0,sizeof(c2)); while(i<l1 && j<l2){ if(j<0|| (query(c2,s2[j]-1)==query(c1,s1[i]-1) && query(c2,s2[j])==query(c1,s1[i])) ) { if (j>-1) update(c2,s2[j],1); if (i>-1) update(c1,s1[i],1); i++;j++; } else { int k=j-1; j=next[j]; for(k;k>=j;k--) {if (k<0)break;update(c2,s2[k],-1);} int tt=i-j; for(tail;tail<tt;tail++) update(c1,s1[tail],-1); } if (j>=l2) { ans[++cnt]=i-j; int k=j-1; j=next[j]; for(k;k>=j;k--) {if (k<0)break;update(c2,s2[k],-1);} int tt=i-j; for(tail;tail<tt;tail++) update(c1,s1[tail],-1); } } return cnt;}int main(){ //freopen("3167in.txt","r",stdin); int n,kk,l1,l2,cnt,i,a; while(scanf("%d%d%d",&n,&kk,&s)!=EOF){ int l1=l2=-1; for(i=1;i<=n;++i){ l1++; scanf("%d",&a); s1[l1]=a; } for(i=1;i<=kk;++i){ l2++; scanf("%d",&a); s2[l2]=a; } s1[++l1]=0; s2[++l2]=0; getnext(next,s2,l2); cnt=KMP(s1,s2,l1,l2,next); printf("%d\n",cnt); for(i=1;i<=cnt;++i){ printf("%d\n",ans[i]+1); } } return 0;}
- poj3167 Cow Patterns KMP、树状数组
- POJ3167 Cow Patterns (KMP)
- [kmp] POJ3167 Cow Patterns
- 【KMP】【poj3167】【bzoj1729】Cow Patterns
- 【KMP】【poj3167】【bzoj1729】Cow Patterns (kmp变形)
- POJ 3167 Cow Patterns (KMP + 树状数组)
- poj3167 Cow Patterns
- poj 3167 Cow Patterns (kmp + 线段树/树状数组)
- [POJ] 3167 Cow Patterns (KMP+树状数组)
- Poj 3167 Cow Patterns Hdu 4749 Parade Show (KMP大小关系相同匹配+树状数组)
- 【POJ3176】Cow Patterns KMP+树状数组(让苍天知道我不认输)
- POJ3167 KMP
- poj 3167 Cow Patterns kmp
- poj3167&hdu4749 KMP+BIT
- pku 3167 Cow Patterns(kmp)
- poj 3167 Cow Patterns(kmp)
- POJ-3167- Cow Patterns(KMP)
- POJ 3167 Cow Patterns KMP+暴力
- 在Centos下用yum安装Mysql时遇到的问题
- oracle job详解
- redhat网易yum源的配置
- OpenCV的susan角点检测
- listctrl重绘
- poj3167 Cow Patterns KMP、树状数组
- 组播的时候到底该如何绑定网卡
- jQuery对表单元素的取值和赋值操作代码
- SPOJ 2713(GSS4-线段树区间开方-多组数据)
- 记住密码
- 在tomcat中运行solr-4.3.0
- List集合正向和逆向排序
- At least one JAR was scanned for TLDs yet contained no TLDs
- Java String object instruction