字符串hash + 二分答案 - 求最长公共子串 --- poj 2774
Long Long Message#
Problem's Link:http://poj.org/problem?id=2774#
Mean:
求两个字符串的最长公共子串的长度。
analyse:
前面在学习后缀数组的时候已经做过一遍了,但是现在主攻字符串hash,再用字符串hash写一遍。
这题的思路是这样的:
1)取较短的串的长度作为high,然后二分答案(每次判断长度为mid=(low+high)>>1是否存在,如果存在就增加下界;不存在就缩小上界);
2)主要是对答案的判断(judge函数)。具体参看代码注释。
Time complexity:O(n)
Source code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | // Memory Time // 1347base 0MS // by : Snarl_jsb // 2014-10-04-21.16 #include<algorithm> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<vector> #include<queue> #include<stack> #include<map> #include<string> #include<climits> #include<cmath> #define ULL unsigned long long using namespace std; string s1,s2; int l1,l2,seed=131; vector<ULL> hash; bool judge( int x) { hash.clear(); ULL tmp=0; for ( int i = 0; i < x; i++) { tmp=tmp* seed + s1[i]; } hash.push_back(tmp); ULL base =1; for ( int i = 1; i < x; i++) { base *= seed; } for ( int i = x; i < l1; i++) { tmp=(tmp*seed+s1[i])- base *s1[i-x]*seed; hash.push_back(tmp); } sort(hash.begin(),hash.end()); ULL hashval = 0; for ( int i = 0; i < x; i++) { hashval = hashval * seed + s2[i]; } if (binary_search(hash.begin(),hash.end(),hashval)) return 1; for ( int i = x; i < l2; i++) { hashval = (hashval-(s2[i-x])* base )*seed+s2[i]; if (binary_search(hash.begin(),hash.end(),hashval)) return 1; } return 0; } int main() { while (cin>>s1>>s2) { l1=s1.size(); l2=s2.size(); int ans = 0; int high = min(l1,l2); int low = 0; while (low <= high) { int mid = (low+high)>>1; if (judge(mid)) { ans = mid; low = mid+1; } else high = mid-1; } printf( "%d\n" ,ans); } return 0; } |
注释代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | // Memory Time // 1347k 0MS // by : Snarl_jsb // 2014-10-04-21.16 #include<algorithm> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<vector> #include<queue> #include<stack> #include<map> #include<string> #include<climits> #include<cmath> #define ULL unsigned long long using namespace std; string s1,s2; int l1,l2,seed=131; vector<ULL> hash; bool judge( int x) { hash.clear(); //多组数据时不要忘了清空全局数组 //构造s1串的hash表 ULL tmp=0; for ( int i = 0; i < x; i++) { tmp=tmp* seed + s1[i]; } hash.push_back(tmp); ULL base =1; for ( int i = 1; i < x; i++) //求出到达x的base值 { base *= seed; } for ( int i = x; i < l1; i++) { tmp=(tmp*seed+s1[i])- base *s1[i-x]*seed; hash.push_back(tmp); } //构造完毕 sort(hash.begin(),hash.end()); //二分查找加速,必需先排序 ULL hashval = 0; for ( int i = 0; i < x; i++) //求出s2串0到x的hash值 { hashval = hashval * seed + s2[i]; } if (binary_search(hash.begin(),hash.end(),hashval)) //查找s2串0到x的hash值是否在s1串的hash表中 return 1; for ( int i = x; i < l2; i++) //如果上面的s2串0到x的hash值未匹配成功,这儿接着匹配s2串长度为x的hash值是否出现在s1串的hash表中 { hashval = hashval*seed+s2[i]-s2[i-x]* base *seed; if (binary_search(hash.begin(),hash.end(),hashval)) return 1; } return 0; } int main() { while (cin>>s1>>s2) { l1=s1.size(); l2=s2.size(); int ans = 0; int low=0,high = min(l1,l2); while (low <= high) //二分答案 { int mid = (low+high)>>1; if (judge(mid)) //判断答案是否可行 { ans = mid; low = mid+1; } else high = mid-1; } printf( "%d\n" ,ans); } return 0; } |
作者:北岛知寒
出处:https://www.cnblogs.com/crazyacking/p/4006441.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?