zoukankan      html  css  js  c++  java
  • HDU 4763:Theme Section(KMP)

    http://acm.hdu.edu.cn/showproblem.php?pid=4763

    Theme Section

    Problem Description
     
    It's time for music! A lot of popular musicians are invited to join us in the music festival. Each of them will play one of their representative songs. To make the programs more interesting and challenging, the hosts are going to add some constraints to the rhythm of the songs, i.e., each song is required to have a 'theme section'. The theme section shall be played at the beginning, the middle, and the end of each song. More specifically, given a theme section E, the song will be in the format of 'EAEBE', where section A and section B could have arbitrary number of notes. Note that there are 26 types of notes, denoted by lower case letters 'a' - 'z'.
    To get well prepared for the festival, the hosts want to know the maximum possible length of the theme section of each song. Can you help us?
     
    Input
     
    The integer N in the first line denotes the total number of songs in the festival. Each of the following N lines consists of one string, indicating the notes of the i-th (1 <= i <= N) song. The length of the string will not exceed 10^6.
    Output
     
    There will be N lines in the output, where the i-th line denotes the maximum possible length of the theme section of the i-th song.
     
    Sample Input
     
    5
    xy
    abc
    aaa
    aaaaba
    aaxoaaaaa
     
    Sample Output
    0
    0
    1
    1
    2
     
    题意:一条串可以分成前中后三个部分,求三个部分最长的相同子串的长度。
    思路:做了好久的KMP一直只会模板题,坚持不看题解,终于花了半天时间搞出这道偏水的题目,主要在于 中间的部分 的定义,该串不包含前面,也不包含后面的部分就是中间,理解错题意瞎搞了好久。我的做法是先劈成三部分,然后先对前后用kmp算最长的公共前后缀长度,然后再把前后缀部分保留,其他全部给中间部分,然后分别再对前面和中间,后面和中间用kmp算出最长的公共子串长度,然后取较小者即可。算是一个比较暴力无脑的做法吧= =。
     
     
      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <string>
      6 using namespace std;
      7 #define N 1000005
      8 string s;
      9 string le, ri, mi, temp;
     10 int nxt[N];
     11 
     12 void make_next(string s)
     13 {
     14     memset(nxt, 0, sizeof(nxt));
     15     int l = s.size();
     16     int j = -1, i = 0;
     17     nxt[0] = -1;
     18     while(i < l) {
     19         if(j == -1 || s[j] == s[i]) {
     20             j++; i++;
     21             nxt[i] = j;
     22         } else {
     23             j = nxt[j];
     24         }
     25     }
     26 }
     27 /*
     28 前面的串和后面的串匹配的时候只能前后缀匹配传入0
     29 前面的串和中间的串匹配或者后面的串和中间的串匹配传入1
     30 */
     31 int kmp(string s, string str, int flag)
     32 {
     33     int l = s.size(), L  = str.size();
     34     make_next(s);
     35     int i = 0, j = 0;
     36     while(i < L && j < l) {
     37         if(j == -1 || s[j] == str[i]) {
     38             i++; j++;
     39             if(flag && j==l) return j;
     40         } else {
     41             j = nxt[j];
     42         }
     43     }
     44     if(i == L) return j;
     45     return 0;
     46 }
     47 
     48 int main()
     49 {
     50     int t;
     51     cin >> t;
     52     while(t--) {
     53         s.clear();
     54         temp.clear();
     55         mi.clear();
     56         le.clear();
     57         ri.clear();
     58         cin >> s;
     59         int len = s.size();
     60         if(len < 3) {
     61             puts("0"); continue;
     62         }
     63         for(int i = 0; i < len; i++) {
     64             if(i <= len/3 - 1) {
     65                 le += s[i];
     66             } else if(i >= len*2/3) {
     67                 ri += s[i];
     68             } else {
     69                 mi += s[i];
     70             }
     71         }//将一条串拆成三部分
     72 
     73         int lo = kmp(le, ri, 0);
     74         if(lo == 0) {
     75             puts("0"); continue;
     76         }
     77         //lo是公共前后缀长度
     78 //        }
     79         for(int i = 0; i < ri.size()-lo; i++)
     80             mi += ri[i];
     81 
     82         for(int i = lo; i < le.size(); i++) {
     83             temp += le[i];
     84         }
     85 
     86         int l = le.size(), r = ri.size();
     87 
     88         ri.erase(0, r - lo);
     89         le.erase(lo, r);
     90         temp += mi;
     91 
     92         int ans = 0;
     93         int k = kmp(le, temp, 1);
     94         int g = kmp(ri, temp, 1);
     95         ans = min(k, g);
     96 
     97         cout << ans << endl;
     98     }
     99     return 0;
    100 }
  • 相关阅读:
    JS(JQEERY) 获取JSON对象中的KEY VALUE
    .NET 日期数据的格式化方法
    jquery转换json对象为字符串
    Repeater和Gridview前台显示行号的方法
    Asp.Net对Json字符串的解析和应用
    C++学习之路—运算符重载(一)概念、方法及规则
    C++学习之路—多态性与虚函数(二)纯虚函数与抽象类
    C++学习之路—多态性与虚函数(一)利用虚函数实现动态多态性
    软件工程师的优秀品质
    C++学习之路—继承与派生(四)拓展与总结
  • 原文地址:https://www.cnblogs.com/fightfordream/p/5697460.html
Copyright © 2011-2022 走看看