[blue《字符串Hash》]同伙

本文探讨了一种字符串匹配问题,即寻找两个字符串中字母序号和相等的子串。介绍了从暴力枚举到使用前缀和及单调队列优化算法的过程,最终实现O(n)的时间复杂度。

标题:同伙
描述:定义所有个字母序号之和相同的字符串为“同伙”。例如“ABC”和“CC”是一伙的,“ABC”和“AAA”不是一伙的。
输入:第一行为S,第二行为字符串SS。
输出:S中从左向右数第一个子串与SS是同伙,字符串的下标从零开始(的异世界生活(雾)),如果没有同伙,输出-1。
范围:|S|,|SS|<=1000000
来源:blue《字符串HASH》

暴力是个好东西。。枚举一下所有子串,然后叠加一下判一下是否相等就ok。

当然这个算法是O(n3)的。

所以想一想如何去优化。

首先可以用前缀和的方法将上面那个算法降一层n,然而O(n2)的复杂度依然承受不起。。。

然而很容易可以发现,这明明就是一个严格上升序列(貌似即使不是也没关系)!

那么就可以去搞单调队列咯,用尺取法不断挪动顺便判一下!

嗯这就是O(n)了,已经达到理论下界了。(附上不太正确的代码。。)

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <queue>
 7 #include <string>
 8 #include <vector>
 9 using namespace std;
10 
11 deque<int>q;
12 string s,ss;
13 long long h,sum,pos,tot;
14 int main(){
15     //freopen("test.in","r",stdin);
16     //freopen("test.out","w",stdout);
17     ios::sync_with_stdio(false);
18     cin>>s>>ss;
19 
20     #define N
21 
22     #ifdef N
23     for(int i=0;i<ss.length();i++)h+=ss[i]-'A'+1;
24     for(int i=0;i<s.length();i++){
25         while(q.size()&&sum>h){
26             sum-=q.back();
27             q.pop_back();
28             pos++;
29         }
30         if(sum==h)break;
31         q.push_front(s[i]-'A'+1);
32         sum+=s[i]-'A'+1;
33     }
34     cout<<(sum==h?pos:-1)<<endl;
35     #endif
36 
37     #ifdef N_3
38     for(int i=0;i<ss.length();i++)h+=ss[i]-'A'+1;
39     for(int i=0;i<s.length();i++){
40         for(int j=0;j<i;j++){
41             sum=0;
42             for(int k=j;k<=i;k++){
43                 sum+=s[k]-'A'+1;
44             }
45             if(sum==h){
46                 cout<<j<<endl;
47                 return 0;
48             }
49         }
50     }
51     #endif
52 
53     #ifdef N_2
54     for(int i=0;i<ss.length();i++)h+=ss[i]-'A'+1;
55     vector<int>v;
56     for(int i=0;i<s.length();i++)v.push_back(s[i]-'A'+1);
57     for(int i=1;i<v.size();i++)v[i]+=v[i-1];
58     for(int i=0;i<s.length();i++){
59         for(int j=0;j<i;j++){
60             if(v[i]-v[max(0,j-1)]==h){
61                 cout<<j<<endl;
62                 return 0;
63             }
64         }
65     }
66     #endif
67     //In Fact,N^2 Algorithm Isn't Slow In Random Tests...(Maybe All The Datas Are Easy To Work On)
68 }
View Code

 (话说为了卡一下暴力和骗分的程序是否应该变成最小满足题意的字串的长度啊。。Orz)

转载于:https://www.cnblogs.com/KingSann/articles/6349041.html

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值