zoukankan      html  css  js  c++  java
  • POJ-2774 后缀数组基础题

    POJ 2774

    题意:求两个字符串的最长公共子串。

    总结:搞了半天还是不太理解,看着大神博客强行敲的。。而且还看到有hash+二分做的。

    // POJ-2774
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<bitset>
    #include<vector>
    #include<set>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define F(i,a,b)  for (int i=a;i<b;i++)
    #define FF(i,a,b) for (int i=a;i<=b;i++)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    typedef long long ll;
    const int N = 3e5+10;
    
    char str[N], str1[N];
    
    //这些应该可以做模板了。。
    int wa[N], wb[N], wsf[N], wv[N], sa[N];
    int rankn[N], height[N], s[N];
    int cmp(int *r, int a, int b, int k)
    {
        return r[a]==r[b] && r[a+k]==r[b+k];
    }
    void Getsa(int *r, int *sa, int n, int m)
    {
        int i, j, p, *x=wa, *y=wb, *t;
        F(i,0,m) wsf[i]=0;
        F(i,0,n) wsf[x[i]=r[i]]++;
        F(i,1,m) wsf[i]+= wsf[i-1];
        for(i=n-1; i>=0; i--) sa[--wsf[x[i]]]=i;
        p=1, j=1;
        for( ; p<n; j*=2, m=p) {
            for(p=0, i=n-j; i<n; i++) y[p++]=i;
            F(i,0,n) if(sa[i]>=j) y[p++]=sa[i]-j;
            F(i,0,n) wv[i]=x[y[i]];
            F(i,0,m) wsf[i]=0;
            F(i,0,n) wsf[wv[i]]++;
            F(i,1,m) wsf[i]+= wsf[i-1];
            for(i=n-1; i>=0; i--) sa[--wsf[wv[i]]]=y[i];
            t=x, x=y, y=t;
            x[sa[0]]=0;
            for(p=1, i=1; i<n; i++)
                x[sa[i]]= cmp(y, sa[i-1], sa[i], j) ? p-1 : p++;
        }
    }
    void Getheight(int *r, int n)
    {
        int i, j, k=0;
        FF(i,1,n) rankn[sa[i]]=i;
        F(i,0,n) {
            if(k) k--;
            else k=0;
            j=sa[rankn[i]-1];
            while(r[i+k]==r[j+k]) k++;
            height[rankn[i]]=k;
        }
    }
    
    
    int main()
    {
        while(~scanf("%s%s", str, str1)) {
            int n=0, len=strlen(str);
            F(i,0,len) s[n++]= str[i]-'a'+1;
            s[n++]=28;
            len=strlen(str1);
            F(i,0,len) s[n++]= str1[i]-'a'+1;
            s[n]=0;    //把两个字符串并到一起,中间和结尾加上标识符
    
            Getsa(s, sa, n+1, 30);
            Getheight(s, n);
            int maxn=0, pos=0;
            len=strlen(str);
            F(i,2,n) if(height[i]>maxn) {   //找出一个height值最大并且i与i-1的sa值分别在两串字符中
                if(0<=sa[i-1] && sa[i-1]<len && len<sa[i])
                    maxn=height[i];
                if(0<=sa[i] && sa[i]<len && len<sa[i-1])
                    maxn=height[i];
            }
            printf("%d
    ", maxn);
        }
    
        return 0;
    }
  • 相关阅读:
    .net调用Oracle存储过程
    Ext.Net基本讲解
    Sql Server数据库中的数据类型和c#的数据类型的映射表
    c#.net常用字符串函数 .
    Extjs & Ext.net中的一些属性
    Oracle表名做为参数 返回值
    Oracle CASE WHEN 用法介绍
    c开发策略之错误处理
    堆和栈的区别
    assert用法总结
  • 原文地址:https://www.cnblogs.com/sbfhy/p/6353298.html
Copyright © 2011-2022 走看看