UVA - 1449 Dominating Patterns (AC自动机)

https://vjudge.net/problem/UVA-1449

题意

 给你n个单词,还有一个长文本s,现在要你输出在文本s中出现次数最多的单词

分析

 AC自动机应用之一:统计每个模板串在原字符串中出现的次数

AC自动机的精华:利用last函数,将模板串的所有子串连接起来,只要沿着边走就可以遍历所有模板串的所有子串

对于重复的模板串题目要求重复输出,因此需要对每一个字符串对应一个序号,这就是它们的输入顺序,这样相同的字符串可以有两个不同的序号。实际上不用map。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ms(a, b) memset(a, b, sizeof(a))
#define pb push_back
#define mp make_pair
#define pii pair<int, int>
//#define eps 0.0000000001
#define IOS ios::sync_with_stdio(0);cin.tie(0);
#define random(a, b) rand()*rand()%(b-a+1)+a
#define pi acos(-1)
//const ll INF = 0x3f3f3f3f3f3f3f3fll;
const int inf = 0x3f3f3f3f;
const int maxn = 1e6 + 10;
const int maxm = 4e5 +10;
const int mod = 20071027;
const int sigma_size = 26;

struct AC{
    int ch[maxn][sigma_size];
    int val[maxn];
    int last[maxn];
    int f[maxn];
    int cnt[maxn];
    int sz;
   
    void init(){
        sz=1;
        memset(ch[0],0,sizeof(ch[0]));
        memset(cnt,0,sizeof(cnt));
      
    }
    int idx(char c){ return c-'a'; }
    void insert(char* s,int v){
        int u = 0,n=strlen(s);
        for(int i=0;i<n;i++){
            int c=idx(s[i]);
            if(!ch[u][c]){
                memset(ch[sz],0,sizeof(ch[sz]));
                val[sz]=0;
                ch[u][c]=sz++;
            }
            u=ch[u][c];
        }
        val[u]=v;
  
    }
    void getFail(){
        queue<int> q;
        f[0]=0;
        for(int c=0;c<sigma_size;c++){
            int u=ch[0][c];
            if(u){
                f[u]=0;
                q.push(u);
                last[u]=0;
            }
        }
        while(!q.empty()){
            int r = q.front();q.pop();
            for(int c=0;c<sigma_size;c++){
                int u = ch[r][c];
                if(!u) {
                    ch[r][c]=ch[f[r]][c];
                    continue;
                }
                q.push(u);
                int v = f[r];
                while(v&&!ch[v][c]) v=f[v];
                f[u]=ch[v][c];
                last[u]=val[f[u]]?f[u]:last[f[u]];
            }
        }
    }
    void find(char* T){
        int n = strlen(T);
        int j=0;
        for(int i=0;i<n;i++){
            int c = idx(T[i]);
            j=ch[j][c];
            if(val[j]) print(j);
            else if(last[j]) print(last[j]);
        }
    }
    void print(int j){
        if(j){
            cnt[val[j]]++;
            print(last[j]);
        }
    }
};
AC ac;
char s[maxn],p[155][88];
int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//    freopen("input.txt", "w", stdout);
#endif
    int n;
    while(scanf("%d",&n)==1&&n){
        ac.init();
        for(int i=1;i<=n;i++){
            scanf("%s",p[i]);
            ac.insert(p[i],i);
        }
        ac.getFail();
        scanf("%s",s);
        ac.find(s);
        int bst=-1;
        for(int i=1;i<=n;i++) bst=max(bst,ac.cnt[i]);
        printf("%d\n",bst);
        for(int i=1;i<=n;i++){
            if(ac.cnt[i]==bst) puts(p[i]);
        }
    }
    return 0;
}

转载于:https://www.cnblogs.com/fht-litost/p/9630077.html

变分模态分解(Variational Mode Decomposition, VMD)是一种强大的非线性、无参数信号处理技术,专门用于复杂非平稳信号的分析与分解。它由Eckart Dietz和Herbert Krim于2011年提出,主要针对传统傅立叶变换在处理非平稳信号时的不足。VMD的核心思想是将复杂信号分解为一系列模态函数(即固有模态函数,IMFs),每个IMF具有独特的频率成分和局部特性。这一过程与小波分析或经验模态分解(EMD)类似,但VMD通过变分优化框架显著提升了分解的稳定性和准确性。 在MATLAB环境中实现VMD,可以帮助我们更好地理解和应用这一技术。其核心算法主要包括以下步骤:首先进行初始化,设定模态数并为每个模态分配初始频率估计;接着采用交替最小二乘法,通过交替最小化残差平方和以及模态频率的离散时间傅立叶变换(DTFT)约束,更新每个模态函数和中心频率;最后通过迭代优化,在每次迭代中优化所有IMF的幅度和相位,直至满足停止条件(如达到预设迭代次数或残差平方和小于阈值)。 MATLAB中的VMD实现通常包括以下部分:数据预处理,如对原始信号进行归一化或去除直流偏置,以简化后续处理;定义VMD结构,设置模态数、迭代次数和约束参数等;VMD算法主体,包含初始化、交替最小二乘法和迭代优化过程;以及后处理,对分解结果进行评估和可视化,例如计算每个模态的频谱特性,绘制IMF的时频分布图。如果提供了一个包含VMD算法的压缩包文件,其中的“VMD”可能是MATLAB代码文件或完整的项目文件夹,可能包含主程序、函数库、示例数据和结果可视化脚本。通过运行这些代码,可以直观地看到VMD如何将复杂信号分解为独立模态,并理解每个模态的物理意义。 VMD在多个领域具有广泛的应用,包括信号处理(如声学、振动、生物医学信号分析)、图像处理(如图像去噪、特征提取)、金融时间序列分析(识
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值