zoukankan      html  css  js  c++  java
  • UVALive4513 Stammering Aliens(哈希法,后缀数组)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=12580

    【思路】

           求出现次数不小于k次的最长可重叠子串和最后的出现位置。

           法一:

                  后缀数组,二分长度,划分height。时间复杂度为O(nlogn)

           法二:

                  Hash法。构造字符串的hash函数,二分长度,求出hash(i,L)后排序,判断是否存在超过k个相同hash 值得块即可。时间为O(nlog2n).

        法三:(UPD.16/4/6)

         SAM。求|right|。

           注意划分height一定要精确且如果m=1需要特判

    【代码1】

     1 //193ms 
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<iostream>
     5 using namespace std;
     6 
     7 const int maxn = 80000+10; 
     8 
     9 int s[maxn];
    10 int sa[maxn],c[maxn],t[maxn],t2[maxn];
    11 void build_sa(int m,int n) {
    12     int i,*x=t,*y=t2;
    13     for(i=0;i<m;i++) c[i]=0;
    14     for(i=0;i<n;i++) c[x[i]=s[i]]++;
    15     for(i=1;i<m;i++) c[i]+=c[i-1];
    16     for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
    17     for(int k=1;k<=n;k<<=1) {
    18         int p=0;
    19         for(i=n-k;i<n;i++) y[p++]=i;
    20         for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
    21         for(i=0;i<m;i++) c[i]=0;
    22         for(i=0;i<n;i++) c[x[y[i]]]++;
    23         for(i=0;i<m;i++) c[i]+=c[i-1];
    24         for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
    25         swap(x,y);
    26         p=1; x[sa[0]]=0;
    27         for(i=1;i<n;i++) 
    28             x[sa[i]]=y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++;
    29         if(p>=n) break;
    30         m=p;
    31     }
    32 }
    33 int rank[maxn],height[maxn];
    34 void getHeight(int n) {
    35     int i,j,k=0;
    36     for(i=0;i<=n;i++) rank[sa[i]]=i;
    37     for(i=0;i<n;i++) {
    38         if(k) k--;
    39         j=sa[rank[i]-1];
    40         while(s[j+k]==s[i+k]) k++;
    41         height[rank[i]]=k;
    42     }
    43 }
    44 int limit,n,pos;
    45 bool can(int L) {    //一定要注意划分height数组的准确性 
    46     pos=-1;
    47     int cnt=1,mx=sa[1];
    48     for(int i=2;i<=n;i++) {
    49         mx=max(mx,sa[i]);
    50         if(height[i]<L) cnt=1,mx=sa[i];
    51         else {
    52             if(++cnt>=limit) pos=max(pos,mx);
    53         }
    54     }
    55     return pos>=0;
    56 }
    57 
    58 char expr[maxn];
    59 int main() {
    60     //freopen("in.in","r",stdin);
    61     //freopen("out.out","w",stdout);
    62     while(scanf("%d",&limit)==1 && limit) {
    63         scanf("%s",expr);
    64         n=strlen(expr);
    65         for(int i=0;i<n;i++) s[i]=expr[i]; s[n]=0;
    66         
    67         build_sa('z'+1,n+1);
    68         getHeight(n);
    69         
    70         if(limit==1) { printf("%d 0
    ",n); continue; }
    71         int L=1,R=n+1;
    72         while(L<R) {
    73             int M=L+(R-L+1)/2;
    74             if(can(M)) L=M; else R=M-1;
    75         }
    76         if(!can(L)) printf("none
    ");
    77         else printf("%d %d
    ",L,pos);
    78     }
    79     return 0;
    80 }
    da

    【代码2】

     1 //1628ms
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 using namespace std;
     7 
     8 typedef unsigned long long ULL;
     9 const int maxn = 80000+10;
    10 const int x = 233;
    11 
    12 ULL hash[maxn],xp[maxn],H[maxn];
    13 int m,n;
    14 char s[maxn];
    15 
    16 int cmp(const int& a,const int& b) {
    17     return hash[a]<hash[b] || (hash[a]==hash[b] && a<b);
    18 }
    19 int pos,rank[maxn];
    20 bool can(int L) {
    21     pos=-1;
    22     for(int i=0;i<n-L+1;i++) hash[i]=H[i]-H[i+L]*xp[L],rank[i]=i;
    23     sort(rank,rank+n-L+1,cmp);
    24     int cnt=0;
    25     for(int i=0;i<n-L+1;i++) {
    26         if(!i || hash[rank[i]]!=hash[rank[i-1]]) cnt=0;
    27         if(++cnt>=m) pos=max(pos,rank[i]);
    28     }
    29     return pos>=0;
    30 }
    31 
    32 int main() {
    33     //freopen("in.in","r",stdin);
    34     //freopen("outr.out","w",stdout);
    35     while(scanf("%d",&m)==1 && m) {
    36         scanf("%s",s);
    37         n=strlen(s);
    38         
    39         H[n]=0,xp[0]=1;
    40         for(int i=n-1;i>=0;i--) H[i]=H[i+1]*x+s[i]-'a';
    41         for(int i=1;i<=n;i++) xp[i]=xp[i-1]*x;
    42         
    43         if(!can(1)) printf("none
    ");
    44         else {
    45             int L=1,R=n+1;
    46             while(L<R) {
    47                 int M=L+(R-L+1)/2;
    48                 if(can(M)) L=M;  else R=M-1;
    49             }
    50             can(L);
    51             printf("%d %d
    ",L,pos);
    52         }
    53     }
    54     return 0;
    55 }
    hash
  • 相关阅读:
    note 11 字典
    note10 元组
    hibernate环境搭建及操作
    JAVA中解决Filter过滤掉css,js,图片文件等问题
    过滤器
    MySQL存储过程(转)
    用java调用oracle存储过程总结(转)
    Oracle分页查询语句的写法(转)
    数据访问类的封装
    事务的特性及事务的隔离级别(转)
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5036751.html
Copyright © 2011-2022 走看看