zoukankan      html  css  js  c++  java
  • 洛谷 P2957 [USACO09OCT]【谷仓里的回声Barn Echoes】

    题目描述

      The cows enjoy mooing at the barn because their moos echo back, although sometimes not completely. Bessie, ever the excellent

      secretary, has been recording the exact wording of the moo as it goes out and returns. She is curious as to just how much overlap there is.

      Given two lines of input (letters from the set a..z, total length in the range 1..80), each of which has the wording of a moo on it, determine the greatest number of characters of   overlap between one string and the other. A string is an overlap between two other strings if it is a prefix of one string and a suffix of the other string.

      By way of example, consider two moos:

      moyooyoxyzooo

      yzoooqyasdfljkamo

      The last part of the first string overlaps 'yzooo' with the first part of the second string. The last part of the second string

      overlaps 'mo' with the first part of the first string. The largest overlap is 'yzooo' whose length is 5.

      POINTS: 50

      奶牛们非常享受在牛栏中哞叫,因为她们可以听到她们哞声的回音。虽然有时候并不能完全听到完整的回音。Bessie曾经是一个出色的秘书,所以她精确地纪录了所有的哞叫声及其回声。她很好奇到底两个声音的重复部份有多长。

      输入两个字符串(长度为1到80个字母),表示两个哞叫声。你要确定最长的重复部份的长度。两个字符串的重复部份指的是同时是一个字符串的前缀和另一个字符串的后缀的字符串。

      我们通过一个例子来理解题目。考虑下面的两个哞声:

      moyooyoxyzooo

      yzoooqyasdfljkamo

      第一个串的最后的部份"yzooo"跟第二个串的第一部份重复。第二个串的最后的部份"mo"跟第一个串的第一部份重复。所以"yzooo"跟"mo"都是这2个串的重复部份。其中,"yzooo"比较长,所以最长的重复部份的长度就是5。

    输入输出格式

    输入格式

      * Lines 1..2: Each line has the text of a moo or its echo

    输出格式

      * Line 1: A single line with a single integer that is the length of the longest overlap between the front of one string and end of the other.

    输入输出样例

    输入样例1

    abcxxxxabcxabcd 
    abcdxabcxxxxabcx 

    输出样例1

    11 
    

    样例说明

      'abcxxxxabcx' is a prefix of the first string and a suffix of the second string.

    解题思路

      这道题可以用字符串做,也可以用字符串哈希做,而在这篇题解中,博客主要用字符串哈希(不会的可以先去看看)来做这道题。

      我们分别给两个字符串记一个哈希值前缀和和哈希值后缀和,在两两比较,哈希值相同就是同一字符串,用ans更新最大值即可。

      这里注意一下存字符串前缀和和存字符串后缀和不一样的方式:

        前缀和:已知999,当继续向后加x,应该999*10+x;

        后缀和:已知999,当继续向前加x,应该x*1000+999;

    题解

     1 #include<bits/stdc++.h>
     2 #define FAST std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0)//优化输入输出,更方便 
     3 typedef unsigned long long ull;
     4 using namespace std;
     5 string x,y;
     6 ull hash1[2][1001];//0是字符串x的前缀和,1是字符串y的前缀和 
     7 ull hash2[2][1001];//0是字符串x的后缀和,1是字符串y的后缀和 
     8 ull mod=212370440130137957ll;//
     9 ull base=11;//进制,在这里就定义一个小的进制了,因为数值过大不方便 
    10 int main()
    11 {
    12     FAST;
    13     cin>>x>>y;
    14     //前缀和操作 
    15     hash1[0][0]=(int)(x[0]);//第一位直接存 
    16     hash1[1][0]=(int)(y[0]);
    17     for(int i=1;i<x.size();i++)//每一位是前面的*base后加上它 
    18     {
    19         hash1[0][i]=hash1[0][i-1]*base+(int)(x[i]);
    20         hash1[0][i]%=mod;//边乘边余 
    21     } 
    22     for(int i=1;i<y.size();i++)//同上 
    23     {
    24         hash1[1][i]=hash1[1][i-1]*base+(int)(y[i]);
    25         hash1[1][i]%=mod;
    26     }
    27     
    28     hash2[0][0]=x[x.size()-1];//最后一位直接存 
    29     hash2[1][0]=y[y.size()-1];
    30     for(int i=x.size()-2;i>=0;i--)//注意,因为是后缀和,所以要倒着来 
    31     {
    32         int qwe=x.size()-i-1;
    33         ull sum=x[i];
    34         while(qwe--)//后缀和
    35         {
    36             sum*=base;
    37             sum%=mod;
    38         }
    39         hash2[0][x.size()-i-1]=hash2[0][x.size()-i-2]+sum;
    40         hash2[0][x.size()-i-1]%=mod;
    41     } 
    42     for(int i=y.size()-2;i>=0;i--)//同上 
    43     {
    44         int qwe=y.size()-i-1;
    45         ull sum=y[i];
    46         while(qwe--)
    47         {
    48             sum*=base;
    49             sum%=mod;
    50         }
    51         hash2[1][y.size()-i-1]=hash2[1][y.size()-i-2]+sum;
    52         hash2[1][y.size()-i-1]%=mod;
    53     } 
    54     int ans=0;
    55     for(int i=0;i<min(x.size(),y.size());i++)
    56     {
    57         if(hash2[0][i]==hash1[1][i])ans=max(ans,i);//如果相等,就取最优值 
    58         if(hash1[0][i]==hash2[1][i])ans=max(ans,i);
    59     }
    60     cout<<ans+1;//因为字符串从0开始,所以要加一 
    61     
    62 }
  • 相关阅读:
    聚集索引和非聚集索引的区别
    转 怎样保存 Checkbox 值
    (转载)多线程:C#线程同步lock,Monitor,Mutex,同步事件和等待句柄(中)
    a=10,b=15,在不用第三方变量的前提下,把a,b的值互换
    (转载)C#多线程编程之:同步事件和等待句柄
    (转载)多线程:C#线程同步lock,Monitor,Mutex,同步事件和等待句柄(上)
    Hello World
    (转)Windows Server 2003中的w3wp.exe进程大量占用cpu资源的各种问题解决方法
    (转,大家共勉) 30岁前男人需要完成的事
    max与top的效率
  • 原文地址:https://www.cnblogs.com/hualian/p/11196883.html
Copyright © 2011-2022 走看看