zoukankan      html  css  js  c++  java
  • POJ2774 很长的信息

    Description

    Little cat在Byterland的首都读物理专业。这些天他收到了一条悲伤地信息:他的母亲生病了。担心买火车票花钱太多(Byterland是一个巨大的国家,因此他坐火车回家需要16小时),他决定只给母亲发短信。 
    Little cat的家境并不富裕,因此他经常去营业厅查看自己发短信花了多少钱。昨天营业厅的电脑坏掉了,打印出两条很长的信息。机智的little cat很快发现: 
    1.信息中所有的字符都是小写英文字母,没有标点和空格。 
    2.所有的短信都被连在了一起——第i+1条短信直接接在第i条短信后面——这就是这两条信息如此长的原因。 
    3.虽然他发的短信都被连在了一起,但由于电脑坏掉了,它们的左边或右边都可能会有许多冗余字符。 
    例如:如果短信是"motheriloveyou",电脑打印出的每条信息都可能是 "hahamotheriloveyou", "motheriloveyoureally", "motheriloveyouornot", "bbbmotheriloveyouaaa",等等。 
    4.因为这些乱七八糟的问题,little cat打印了两遍(所以有两条非常长的信息)。尽管原始的短信文本在两条信息中都一样,但两条信息在文本两侧的冗余字符都可能不一样。 
    给出这两条很长的信息,输出little cat写下的原始短信文本的最长可能长度。 
    背景: 
    在Byterland,短信按照美元/字节的单位计价。这就是little cat想要知道原始文本最长可能长度的原因。 
    为什么让你写一个程序?有四个原因: 
    1.little cat这些天忙于他的物理课程。 
    2.little cat不想透露他对母亲说了什么。 
    3.POJ是个好网站。 
    4.little cat想要从POJ那里挣点钱,并尝试说服他的母亲去医院

    Input

    两行两个由小写英文字母组成的字符串。字符串长度都不会超过100000

    Output

    一行一个整数,即little cat写下的原始文本的最长可能长度。

    Sample Input

    yeshowmuchiloveyoumydearmotherreallyicannotbelieveit 
    yeaphowmuchiloveyoumydearmother

    Sample Output

    27

    题解:

    将两串合并,中间插入一个'#'保证high不会交叉

    直接求出hight数组然后找出满足sa分别在两串的最大hight值

     1 #include <algorithm>
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 using namespace std;
     8 const int N=200005;
     9 char S1[N],S2[N];int s[N],n,c[N],sa[N],y[N],x[N],rk[N];
    10 bool comp(int i,int j,int k){
    11     return y[i]==y[j] && y[i+k]==y[j+k];
    12 }
    13 void getSA(){
    14     int m=31,t=0;
    15     for(int i=0;i<=m;i++)c[i]=0;
    16     for(int i=1;i<=n;i++)c[x[i]=s[i]]++;
    17     for(int i=1;i<=m;i++)c[i]+=c[i-1];
    18     for(int i=n;i>=1;i--)sa[c[x[i]]--]=i;
    19     for(int k=1;k<=n;k<<=1){
    20         t=0;
    21         for(int i=0;i<=m;i++)y[i]=0;
    22         for(int i=n-k+1;i<=n;i++)y[++t]=i;
    23         for(int i=1;i<=n;i++)if(sa[i]>k)y[++t]=sa[i]-k;
    24         for(int i=0;i<=m;i++)c[i]=0;
    25         for(int i=1;i<=n;i++)c[x[i]]++;
    26         for(int i=1;i<=m;i++)c[i]+=c[i-1];
    27         for(int i=n;i>=1;i--)sa[c[x[y[i]]]--]=y[i];
    28         swap(x,y);
    29         t=x[sa[1]]=1;
    30         for(int i=2;i<=n;i++)x[sa[i]]=comp(sa[i-1],sa[i],k)?t:++t;
    31         if(t==n)break;
    32         m=t;
    33     }
    34     for(int i=1;i<=n;i++)rk[sa[i]]=i;
    35 }
    36 int high[N];
    37 void gethight(){
    38     int h=0,j;
    39     for(int i=1;i<=n;i++){
    40         j=sa[rk[i]-1];
    41         if(h>0)h--;
    42         for(;j+h<=n && i+h<=n;h++)
    43             if(s[i+h]!=s[j+h])break;
    44         high[rk[i]-1]=h;
    45     }
    46 }
    47 void work()
    48 {
    49     n=0;
    50     scanf("%s%s",S1,S2);
    51      for(int i=0,sz=strlen(S1);i<sz;i++)s[++n]=S1[i]-'a'+1;
    52     s[++n]=30;
    53     for(int i=0,sz=strlen(S2);i<sz;i++)s[++n]=S2[i]-'a'+1;
    54     getSA();
    55     gethight();
    56     int ans=0;int tx=strlen(S1);
    57     for(int i=1;i<n;i++)if(high[i]>ans && ((sa[i]<=tx)!=(sa[i+1]<=tx)))ans=high[i];
    58     printf("%d
    ",ans);
    59 }
    60 
    61 int main()
    62 {
    63     work();
    64     return 0;
    65 }
  • 相关阅读:
    算法的学习 — 冒泡排序
    自定义UICollectionLayout布局 —— UIKit之学习UICollectionView记录一《瀑布流》
    HDU 1541 Stars (线段树||树状数组)
    HDU 1617 Phone List (排序||字典树)
    CSU 1312 CX and girls (最短路)
    CSU 1320 Scoop water (卡特兰数)
    POJ 1838 Banana (并查集)
    POJ 1837 Balance (DP)
    POJ 1088 滑雪 (记忆化搜索)
    TYVJ 1261 可达总数 (BFS)
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7152722.html
Copyright © 2011-2022 走看看