题目:在一个串中找到至少出现m次的最长的串。
思路:直接hash,然后二分答案。
/* * @author: Cwind * http://www.cnblogs.com/Cw-trip/ */ //#pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <map> #include <algorithm> #include <cstdio> #include <cstring> #include <cstdlib> #include <vector> #include <queue> #include <stack> #include <functional> #include <set> #include <cmath> using namespace std; #define IOS std::ios::sync_with_stdio(false);std::cin.tie(0) #define pb push_back #define PB pop_back #define bk back() #define fs first #define se second #define sq(x) (x)*(x) #define eps 0.00000001 #define IINF (1<<29) #define LINF (1ll<<59) typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; typedef pair<ll,ll> P; const int maxl=4e4+300; const ull hash1=123; int m; char s[maxl]; ull H[maxl]; ull xp[maxl]; ull gethash(int i,int L){ return H[i]-H[i+L]*xp[L]; } int len; map<ull,vector<int> > mp; map<ull,int> cont; map<ull,vector<int> >::iterator it; ull val[maxl]; bool check(int l){ for(int i=0;i<len-l+1;i++){ val[i]=gethash(i,l); } sort(val,val+len-l+1); int c=0; for(int i=0;i<len-l+1;i++){ if(i==0||val[i]!=val[i-1]) c=1; if(val[i]==val[i-1]) c++; if(c>=m) return true; } return false; } void getans(int l){ mp.clear(); for(int i=0;i+l<=len;i++){ mp[gethash(i,l)].pb(i); } } void init(){ xp[0]=1; for(int i=1;i<maxl;i++){ xp[i]=xp[i-1]*hash1; } } int main(){ freopen("/home/files/CppFiles/in","r",stdin); init(); while(cin>>m,m){ scanf("%s",s); len=strlen(s); H[len]=0; for(int i=len-1;i>=0;i--){ H[i]=H[i+1]*hash1+(ull)s[i]; } int l=0,r=len+1; while(r-l>1){ int mid=(r+l)/2; if(check(mid)){ l=mid; }else{ r=mid; } } if(l==0){ puts("none"); continue; } getans(l); vector<int> pos; for(it=mp.begin();it!=mp.end();it++){ if(it->se.size()>=m){ sort(it->se.begin(),it->se.end()); pos.pb(it->se.bk); } } sort(pos.begin(),pos.end()); printf("%d %d\n",l,pos.bk); } return 0; }
时间: 2024-10-19 06:53:38