• 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 }
  • 相关阅读:
    .net core 学习小结之 配置介绍(config)以及热更新
    .net core 学习小结之环境配置篇
    powershell下载网站图片
    Powershell 脚本输出前十条消耗内存的进程到excel
    Linux 自学shell
    使用bat脚本进行开机启动批处理
    Git 创建分支并合并主分支
    Git 的使用及其一些基本用法
    点击按钮复制文本到剪切板
    关于一些基本排序的实现
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/5150118.html
Copyright © 2020-2023  润新知