题意是给出一些子串,用这些子串能拼出一个S的前缀来,问这个前缀最长能有多长。
做法是,从S的第一个元素开始扫,到S[i]时,查看每一个长度不大于i的子串,然后检查这个子串能否和以i为结尾,长度与这个子串长度相同的S的子串匹配,
若能匹配,则检查在以S[i-子串长度] 为结尾处能否找到以前匹配到S[i-子串长度]的标记,
/* ID: modengd1 PROG: prefix LANG: C++ */ #include <iostream> #include <string> #include <cstring> #include <stdio.h> #include <memory.h> #include <vector> using namespace std; int main() { freopen("prefix.in","r",stdin); freopen("prefix.out","w",stdout); vector<string> elements; string S,element; bool endTag[200001]; char temp; int ans=0; memset(endTag,false,sizeof(endTag)); while(true)//循环输入多个元素 { element.clear(); while(scanf("%c",&temp)&&temp!=‘ ‘&&temp!=‘\n‘) { element.push_back(temp); } if(element[0]==‘.‘) break; elements.push_back(element); } while(scanf("%c",&temp)!=EOF)//输入S { if(temp==‘\n‘) continue; S.push_back(temp); } endTag[0]=true; for(int i=1;i<=S.size();i++) { for(int j=0;j<elements.size();j++) { string now=elements[j]; bool ismath=true; if(now.size()>i) break; //检查当前元素是否能以i结尾的,长度为now.size()的S的字串匹配 for(int k=now.size()-1;k>=0;k--) { if(S[i-1-k]!=now[now.size()-k-1]) { ismath=false; break; } } //如果能匹配,检查是否存在以前匹配过的i-now.szie()的结尾标记 if(ismath&&endTag[i-now.size()]) { endTag[i]=true; ans=i; break; } } } cout<<ans<<endl; return 0; }
能找到的话说明可以在S[i]处加标记。最后找到加的最远的一个标记就是题目要的答案。
原文:http://www.cnblogs.com/modengdubai/p/4781939.html