POJ-1743 Musical Theme 字符串問題 不重疊最長重復子串
阿新 • • 發佈:2018-08-03
pro _id hashmap a* memset 找到 pla 構建 ext logn))
剛從藍書看來的,然而本題對hash表要求很高(能夠處理unsigned long long大小鍵值)
那個簡潔的HashMap還是要改改
題目鏈接:https://cn.vjudge.net/problem/POJ-1743
題意
給一串整數,問最長不可重疊最長重復子串有多長
註意這裏匹配的意思是匹配串的所有元素可以減去或者加上某個值
例: 34 30 26 22 18 82 78 74 70 66
後5個整數的串可以匹配前5個數
思路
LCP問題(最長公共前綴)
兩個思路
- 後綴數組
對height數組二分長度,找到height大於len且兩字符串起點差值大於len的情況下,len最大值 - 哈希+二分
二分長度,哈希值比較字符串找到當前len下符合要求子串即可
這題我用的第二個思路
首先差分一下,然後二分長度,用哈希的方法比較兩個字符串O(1)
總復雜度O(nlog)(初始化O(n)+二分O(1n
剛從藍書看來的,然而本題對hash表要求很高(能夠處理unsigned long long大小鍵值)
那個簡潔的HashMap還是要改改
具體寫下好了
首先構建一個H數組,具體的
\[ H[i]= \sum S[i] base^{n-i-1} \]
對一個以i為起點,len為長度的字符串,他的Hash值:
\[ Hash(i, len)=H[i]-H[i+len] base^len \]
然後O(n)的字符串比較復雜度降到O(1)
這裏可能會撞hash,所以保險一點咱還得再直接判斷是否相同
提交過程
WA*n | |
TLE*n | |
AC |
代碼
#include <cstdio> #include <cstring> const int maxn=2e4+20; const int HASH = 10007; const int MAXN = 20010; const unsigned long long hashBase=13331; struct HASHMAP{ int head[HASH],next[MAXN],size; unsigned long long state[MAXN]; int f[MAXN]; void init(){ size = 0; memset(head,-1,sizeof(head)); } int insert(unsigned long long val,int _id){ int h = val%HASH; for(int i = head[h]; i != -1;i = next[i]) if(val == state[i]) return f[i]; f[size] = _id; state[size] = val; next[size] = head[h]; head[h] = size++; return f[size-1]; } }hash; unsigned long long hashBasePow[maxn], H[maxn]; int str[maxn], n; bool judge(int len){ hash.init();// hash.clear(); for(int i=0; i<n-len; i++){ unsigned long long key=H[i]-H[i+len]*hashBasePow[len]; if (hash.insert(key, i)<i-len) return true; }return false; } int solve(void){ int ans=0; int l=4, r=n-1; while(l<=r){ int mid=l+(r-l)/2; if(judge(mid)) ans=mid, l=mid+1; else r=mid-1; } if(ans<4) ans=-1; return ans+1; } int main(){ hashBasePow[0]=1; for(int i=1; i<maxn; i++) hashBasePow[i]=hashBasePow[i-1]*hashBase; while(scanf("%d", &n)==1 && n){ for (int i=0; i<n; i++) scanf("%d", &str[i]); for (int i=0; i<n-1; i++) str[i]-=str[i+1]; H[n-1]=str[n-1]; for (int i=n-2; i>=0; i--) H[i]=H[i+1]*hashBase+str[i]; printf("%d\n", solve()); } return 0; }
Time | Memory | Length | Lang | Submitted |
---|---|---|---|---|
547ms | 1080kB | 1557 | G++ | 2018-08-03 15:26:17 |
POJ-1743 Musical Theme 字符串問題 不重疊最長重復子串