[String hash] Ybt_ word recitation

topic

Give you some words, and then give you an article.
I want you to find out how many given words are included in this article.
Then find a paragraph in the article, make it contain the most words given (without weight), and output its minimum length.


solution

String hash, and then ruler.
The rule-taking method usually refers to the method of saving a pair of subscripts (starting point, end-point) in the array, and then alternately advancing the two endpoints according to the actual situation until the answer is obtained. This operation is very similar to the way the ruler takes the insect to crawl, hence the name.
Double hashing prevents duplication of hash values.


Code

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int ls, flag, ans1, ans2, lans, n, t, l[100010], k1[100010], k2[100010];
bool b[100010];
string s[100010], ss;
struct asdf{
    
    
	int z, next;
} a[100010];
int main(){
    
    
	scanf("%d", &n);
	for(int i = 1; i <= n; ++i){
    
      //读入单词
		cin >> ss;
		ls = ss.size(); 
		int kk1 = 0, kk2 = 0; 
		for(int j = 0; j < ls; ++j)
			kk1 = (kk1 * 13331 + ss[j]) % 10003;
		for(int j = 0; j < ls; ++j)
			kk2 = (kk2 * 10007 + ss[j]) % 10003;
		a[++t] = (asdf){
    
    kk2, l[kk1]}; l[kk1] = t;  //邻接表储存
	}
	scanf("%d", &n);
	ans2 = n;
	for(int i = 1; i <= n; ++i){
    
      //读入文章单词
		cin >> s[i];
		ls = s[i].size(); 
		for(int j = 0; j < ls; ++j)  //计算其哈希值
			k1[i] = (k1[i] * 13331 + s[i][j]) % 10003;
		for(int j = 0; j < ls; ++j)
			k2[i] = (k2[i] * 10007 + s[i][j]) % 10003;
		for(int j = l[k1[i]]; j; j = a[j].next)  //判断是否是要背诵的单词
		  	if(a[j].z == k2[i] && b[j] == 0){
    
    
		    	b[j] = 1;
		  		++ans1; //是。统计入答案
		  		break;
		  	}
	}
	for(int i = 1; i <= n - ans1 + 1; ++i){
    
      //尺取法
		memset(b, 0, sizeof(b));
		lans = 0;
		for(int j = i; j <= n; ++j){
    
    
			for(int k = l[k1[j]]; k; k = a[k].next) 
		    	if(a[k].z == k2[j]){
    
    //如果这个单词是要背的
		  			if(b[k] == 0){
    
      //取的这段中没出现过
		  				b[k] = 1;
		  				++lans;  //计入答案
					}
		  			break;
		  		}
		  	if(lans == ans1) {
    
      //如果背完所需的了
		  		ans2 = min(ans2, j - i + 1); //取最小长度
		  		break;
			}
		}
	}
	printf("%d\n%d", ans1, ans2);  //输出答案
}  

Guess you like

Origin blog.csdn.net/qq_42937087/article/details/115015172