• [NOI Online 2021 提高组] 岛屿探险


    思路不说了。
    想起来自己打比赛的时候,没睡好。随便写了个(HASH),模数开小一半分都没有。
    然后学了(SAM),发现这个判重不就是个水题。
    (SAM)是字串tire的集合体。
    随便(dfs)一下就好,然后复杂度是(O(n^2))即遍历所有子串

    [NOI Online 2021 提高组] 岛屿探险
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define ll long long
    #define N 3005
    #define end 0x3f3f3f3f
    
    ll n;
    char a[N],b[N];
    ll nex[N][30];
    
    ll ch[N << 1][30],link[N << 1],len[N << 1],nod = 1,las = 1;//SAM
    
    inline void insert(ll c){
    	ll p = las,q = ++nod;las = q;
    	len[q] = len[p] + 1;
    	while(!ch[p][c] && p != 0){
    		ch[p][c] = q;
    		p = link[p];
    	}
    	if(p == 0)
    	link[q] = 1;
    	else{
    		ll x = ch[p][c];
    		if(len[x] == len[p] + 1){
    			link[q] = x;
    		}else{
    			int y = ++ nod ;//复制一个新节点
    			link[y] = link[x];
    			link[x] = link[q] = y;
    			len[y] = len[p] + 1;
    			std::memcpy(ch[y],ch[x],sizeof(ch[x])); 
    			while(p != 0 && ch[p][c] == x){
    				ch[p][c] = y;
    				p = link[p];
    			}
    		}
    	}
    }
    
    ll ans;
    
    inline void dfs(int u,int to,ll now){
    	if(to == end)
    	return;
    	ans ++ ;
    	for(int i = 0;i <= 26;++i){
    		if(ch[u][i])
    		dfs(ch[u][i],nex[to + 1][i],now * 10 + i);
    	}
    }
    
    int main(){
    	scanf("%lld",&n);
    	scanf("%s%s",a + 1,b + 1);
    	for(int i = 0;i <= 26;++i)
    	nex[n + 1][i] = end;
    	for(int i = n;i >= 1;--i){
    	for(int j = 0;j <= 26;++j)
    	nex[i][j] = nex[i + 1][j];
    	nex[i][a[i] - 'a'] = i;
    	}
    	for(int i = 0;i <= 26;++i)
    	nex[0][i] = nex[1][i];
    	for(int i = 1;i <= n;++i)
    	insert(b[i] - 'a');
    	dfs(1,0,0);
    	std::cout<<ans - 1<<std::endl;
    }
    
  • 相关阅读:
    软件构造—— 实验二 lex词法分析
    软件构造-实验1 根据状态转换图手工构造词法扫描器
    PHP——实验四 PHP操作数据库
    判断是不是素数
    hexo和github pages的关系
    Python的map,reduce,filter函数
    CentOS源码更新Linux最新内核
    CentOS打Meltdown等漏洞的补丁包
    let申明与const申明
    正则表达式
  • 原文地址:https://www.cnblogs.com/dixiao/p/14897104.html
Copyright © 2020-2023  润新知