zoukankan      html  css  js  c++  java
  • POJ 3294 二分找超过一半字符串中存在的子串

    题目大意:

    给定n个字符串,求出现在不小于k/2个字符串中的最长子串。 

    二分找对应子串长度的答案,将所有字符串链接成一个长字符串求后缀数组,记录每一个位置本属于第几个字符串,利用height查询的时候,

    根据记录的位置不断判断是否出现重复的字符串是在同一个字符串内的

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <vector>
      4 #include <iostream>
      5 using namespace std;
      6 typedef long long ll;
      7 const int N = 200010;
      8 int r[N] , sa[N] , rank[N] , height[N];
      9 int K , wa[N] , wb[N] , wv[N] , wsf[N];
     10 int cmp(int *r , int a , int b , int l){return r[a]==r[b]&&r[a+l]==r[b+l];}
     11 void da(int *r , int *sa , int n , int m)
     12 {
     13     int i,j,p,*x=wa,*y=wb,*t;
     14     for(i=0;i<m;i++)wsf[i]=0;
     15     for(i=0;i<n;i++)wsf[x[i]=r[i]]++;
     16     for(i=1 ; i<m ; i++) wsf[i]+=wsf[i-1];
     17     for(i=n-1;i>=0;i--) sa[--wsf[x[i]]]=i;
     18     for(j=1,p=1;p<n;j*=2,m=p){
     19         for(p=0,i=n-j;i<n;i++) y[p++]=i;
     20         for(i=0;i<n;i++) if(sa[i]>=j)y[p++]=sa[i]-j;
     21         for(i=0;i<n;i++) wv[i]=x[y[i]];
     22         for(i=0;i<m;i++) wsf[i]=0;
     23         for(i=0;i<n;i++) wsf[wv[i]]++;
     24         for(i=1;i<m;i++) wsf[i]+=wsf[i-1];
     25         for(i=n-1;i>=0;i--) sa[--wsf[wv[i]]]=y[i];
     26         for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
     27             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
     28     }
     29     return;
     30 }
     31 void callHeight(int *r , int *sa , int n)
     32 {
     33     int i,j,k=0;
     34     for(i=1;i<=n;i++) rank[sa[i]]=i;
     35     for(i=0;i<n;height[rank[i++]]=k)
     36         for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
     37     return;
     38 }
     39 #define ll long long
     40 int n , len , pos[105][2] , dif , mp[N];
     41 bool vis[105];
     42 char s[105][1005] , all[N];
     43 vector<int> ans , tmp;
     44 bool check(int mid)
     45 {
     46     tmp.clear();
     47     bool flag = false;
     48     memset(vis , 0 , sizeof(vis));
     49     int cnt = 1 , rec = sa[0];
     50     vis[sa[0]] = true;
     51     for(int i=1 ; i<len ; i++){
     52         if(height[i]<mid){
     53             if(cnt>n/2){
     54                 tmp.push_back(rec);
     55                 flag = true;
     56             }
     57             memset(vis , 0 , sizeof(vis));
     58             cnt = 1 , vis[mp[sa[i]]] = true , rec = sa[i];
     59         }
     60         else{
     61             if(!vis[mp[sa[i]]]){
     62                 vis[mp[sa[i]]] = true;
     63                 cnt++;
     64                 rec = sa[i];
     65             }
     66         }
     67     }
     68     if(flag) ans = tmp;
     69     return flag;
     70 }
     71 int bin_search()
     72 {
     73     int l=0 , r=1000 , ans=0 , mid;
     74     while(l<=r){
     75         mid = (l+r)>>1;
     76         if(check(mid)) l=mid+1 , ans=mid;
     77         else r=mid-1;
     78     }
     79     return ans;
     80 }
     81 int main()
     82 {
     83    // freopen("a.in" , "r" , stdin);
     84     bool flag = false;
     85     while(scanf("%d" , &n) , n){
     86         if(flag) puts("");
     87         flag = true;
     88         len = 0 , dif = 27;
     89         for(int i=0 ; i<n ; i++){
     90             scanf("%s" , s[i]);
     91             for(int j=0 ; j<strlen(s[i]) ; j++) all[len] = s[i][j] , mp[len]=i+1 , r[len++] = s[i][j]-'a'+1;
     92             pos[i][0] = len;
     93             all[len] = '*';
     94             mp[len]=i+1 , r[len++] = dif++;
     95         }
     96         r[len-1] = 0;
     97         da(r , sa , len , dif);
     98        // for(int i=0 ; i<len ; i++) cout<<"i: "<<i<<" "<<sa[i]<<endl;
     99         callHeight(r , sa , len-1);
    100         int ret = bin_search();
    101         if(!ret) puts("?");
    102         else{
    103             for(int i=0 ; i<ans.size() ; i++){
    104                 for(int j=ans[i] , t=0 ; t<ret ; j++ , t++) printf("%c" , all[j]);
    105                 puts("");
    106             }
    107         }
    108     }
    109 }
  • 相关阅读:
    javaScript中eval()方法转换json对象
    JS 根据参数是否为空进行true|false判断呢
    mybatis返回map类型数据空值字段不显示(三种解决方法)
    值类型与引用类型的区别
    随机生成四位数字和字母
    彩票
    冒泡排序
    查询资料:二分查找法
    随机数生成机制
    运算符
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/5150118.html
Copyright © 2011-2022 走看看