Codeforces Round #269 (Div. 2) D(KMP)

题目链接:http://codeforces.com/group/1EzrFFyOc0/contest/471/problem/D

题目思路:这题主要就是两张图的匹配吧(可重叠),因为墙上下可以移动,其实就是匹配轮廓了,完全可以用KMP,KMP第一题纪念一下,果然还是菜啊。

至于KMP感觉这篇博文不错:http://blog.csdn.net/starstar1992/article/details/54913261

AC代码:

#include <cstdio>  
#include <cstdlib>  
#include <cstring>  
#include <cmath>  
#include <cctype>  
#include <iostream>  
#include <algorithm>  
#include <string>  
#include <vector>  
#include <queue>  
#include <map>  
#include <set>  
#include <sstream>  
#include<iomanip>  
using namespace std;  
typedef long long ll;  
#define inf int(0x3f3f3f3f)  
#define mod int(1e9+7)  
#define pi acos(-1)  
inline int read()  
{  
    int X=0,w=0; char ch=0;  
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}  
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();  
    return w?-X:X;  
}  
int c[200008],d[200008],ne[200008];  
void cal(int w)  
{  
    ne[0]=-1;  
    int k=-1,i=0;  
    while(i<w)  
    {  
        while(k>-1&&d[k]!=d[i])  
        {  
            k=ne[k];  
        }  
        if(d[k]==d[i]||k==-1)  
        {  
            k++;  
        }  
        ne[++i]=k;  
    }  
    return;  
}  
int kmp(int n,int w)  
{  
    int k=0,s=0;  
    for(int i=0;i<n;i++)  
    {  
        while(k>0&&d[k]!=c[i])  
        {  
            k=ne[k];  
        }  
        if(d[k]==c[i])  
        {  
            k++;  
        }  
        if(k==w)  
        {  
            s++;  
            k=ne[k];  
        }  
    }  
    return s;  
}  
int main()  
{  
    int n,w;  
    while(cin>>n>>w)  
    {  
        memset(ne,0,sizeof(ne));  
        for(int i=0;i<n;i++)  
        {  
            c[i]=read();  
        }  
        for(int i=0;i<n-1;i++)  
        {  
            c[i]=c[i+1]-c[i];  
        }  
        for(int i=0;i<w;i++)  
        {  
            d[i]=read();  
        }  
        for(int i=0;i<w-1;i++)  
        {  
            d[i]=d[i+1]-d[i];  
        }  
        cal(w-1);  
        int s=0;  
        s=kmp(n-1,w-1);  
        if(w==1)  
        {  
            s=n;  
        }  
        cout<<s<<endl;  
    }  
    return 0;  
}  

还有HDU2087:http://acm.hdu.edu.cn/showproblem.php?pid=2087(这个是不能重叠的,其实差不多QAQ)

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <sstream>
#include<iomanip>
using namespace std;
typedef long long ll;
#define inf int(0x3f3f3f3f)
#define mod int(1e9+7)
#define pi acos(-1)
inline int read()
{
    int X=0,w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
int ne[1008];
string c,d;
void cal(int w)  
{  
    ne[0]=-1;  
    int k=-1,i=0;  
    while(i<w)  
    {  
        while(k>-1&&d[k]!=d[i])  
        {  
            k=ne[k];  
        }  
        if(d[k]==d[i]||k==-1)  
        {  
            k++;  
        }  
        ne[++i]=k;  
    }  
    return;  
}  
int kmp(int n,int w)
{
    int k=0,s=0;
    for(int i=0;i<n;i++)
    {
        while(k>0&&d[k]!=c[i])
        {
            k=ne[k];
        }
        if(d[k]==c[i])
        {
            k++;
        }
        if(k==w)
        {
            s++;
            k=-1;
        }
    }
    return s;
}
int main()
{
    while(cin>>c)
    {
        int n,w;
        if(c=="#")
        {
            break;
        }
        cin>>d;
        n=c.size();w=d.size();
        memset(ne,0,sizeof(ne));
        cal(w);
        int s;
        s=kmp(n,w);
        cout<<s<<endl;
    }
    return 0;
}

还有洛谷的3375

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <bitset>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll inff = 0x3f3f3f3f3f3f3f3f;
#define FOR(i,a,b) for(int i(a);i<=(b);++i)
#define FOL(i,a,b) for(int i(a);i>=(b);--i)
#define REW(a,b) memset(a,b,sizeof(a))
#define inf int(0x3f3f3f3f)
#define si(a) scanf("%d",&a)
#define sl(a) scanf("%I64d",&a)
#define sd(a) scanf("%lf",&a)
#define ss(a) scanf("%s",a)
#define mod int(1e9+7)
#define pb push_back
#define lc (d<<1)
#define Pll pair<ll,ll>
#define P pair<int,int>
#define pi acos(-1)
string c,d;
int ne[1000008];
void cal(int w)
{
    ne[0]=-1;
    int k=-1,i=0;
    while(i<w)
    {
        while(k>-1&&d[k]!=d[i])  k=ne[k];
        if(k==-1||d[k]==d[i])  k++;
        ne[++i]=k;
    }
}
int kmp(int n,int w)
{
    int k=0,i=0;
    while(i<n)
    {
        while(k>0&&d[k]!=c[i])  k=ne[k];
        if(d[k]==c[i])  k++;
        if(k==w)  cout<<i-w+2<<endl,k=ne[k];
        i++;
    }
}
int main()
{
    cin.tie(0);
    cout.tie(0);
    cin>>c>>d;
    cal(d.size());
    kmp(c.size(),d.size());
    cout<<ne[1];
    for(int i=2;i<=d.size();i++)  cout<<" "<<ne[i];
    puts("");
    return 0;
}

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值