UVa Live 4670 Dominating Patterns - Aho-Corasick自动机

题目传送门

  快速的通道I

  快速的通道II

题目大意

  给定一堆短串,和一个文本串,问哪些短串在文本串中出现的次数最多。

  我觉得刘汝佳的做法,时间复杂度有问题。只是似乎这道题短串串长太短不好卡。比如给出的串是一坨$a$。暴力跳$last$会比较gg。

  考虑如何计算一个短串在长串中的出现次数。

  当短串在长串的某个位置出现的时候,这意味着它的结束位置在fail树上的祖先中某个状态是短串的终止状态。

  我们会在长串经过的每个状态都去做这样一个操作来统计每个短串出现的次数。

  这个可以看成在fail树上的以根为端点的链上修改操作。

  由于询问可以看成是离线的,所以每次可以单点修改cnt,最后做一次前缀和。

Code

  1 /**
  2  * UVa Live
  3  * Problem#4670
  4  * Accepted
  5  * Time: 45ms
  6  */
  7 #include <iostream>
  8 #include <cstring>
  9 #include <cstdio>
 10 #include <queue>
 11 using namespace std;
 12 typedef bool boolean;
 13 
 14 const int MaxNode = 10505, N = 152, L = 75;
 15 
 16 typedef class TrieNode {
 17     public:
 18         int cnt;
 19         TrieNode* ch[26];
 20         TrieNode* fail;
 21 }TrieNode;
 22 
 23 TrieNode pool[MaxNode];
 24 TrieNode *top;
 25 
 26 TrieNode* newnode() {
 27     top->cnt = 0;
 28     memset(top->ch, 0, sizeof(top->ch));
 29     top->fail = NULL;
 30     return top++;
 31 }
 32 
 33 typedef class AhoCorasick {
 34     public:
 35         TrieNode* rt;
 36 
 37         AhoCorasick() {
 38             top = pool;
 39             rt = newnode();
 40         }
 41 
 42         TrieNode* insert(char* str) {
 43             TrieNode* p = rt;
 44             for (int i = 0, c; str[i]; i++) {
 45                 c = str[i] - 'a';
 46                 if (!p->ch[c])
 47                     p->ch[c] = newnode();
 48                 p = p->ch[c];
 49             }
 50             return p;
 51         }
 52 
 53         void build() {
 54             queue<TrieNode*> que;
 55             rt->fail = NULL;
 56             que.push(rt);
 57             while (!que.empty()) {
 58                 TrieNode* p = que.front();
 59                 que.pop();
 60                 for (int i = 0; i < 26; i++) {
 61                     TrieNode *np = p->ch[i];
 62                     if (!np)    continue;
 63                     que.push(np);
 64                     TrieNode* f = p->fail;
 65                     while (f && !f->ch[i])    f = f->fail;
 66                     if (!f)
 67                         np->fail = rt;
 68                     else
 69                         np->fail = f->ch[i];
 70                 }
 71             }
 72         }
 73 
 74         void query(char *str) {
 75             TrieNode *p = rt;
 76             for (int i = 0; str[i]; i++) {
 77                 int c = str[i] - 'a';
 78                 while (p && !p->ch[c])    p = p->fail;
 79                 if (!p)
 80                     p = rt;
 81                 else
 82                     p = p->ch[c];
 83                 p->cnt++;    
 84             }
 85             for (p = top - 1; p != pool; p--)
 86                 p->fail->cnt += p->cnt;
 87         }
 88 }AhoCorasick;
 89 
 90 int n;
 91 AhoCorasick ac;
 92 char S[1000005];
 93 char T[N][L];
 94 TrieNode* ps[N];
 95 
 96 inline boolean init() {
 97     scanf("%d", &n);
 98     if (!n)    return false;
 99     ac = AhoCorasick();
100     for (int i = 1; i <= n; i++) {
101         scanf("%s", T[i]);
102         ps[i] = ac.insert(T[i]);
103     }
104     scanf("%s", S);
105     return true;
106 }
107 
108 inline void solve() {
109     ac.build();
110     ac.query(S);
111     int maxt = 0;
112     for (int i = 1; i <= n; i++)
113         if (ps[i]->cnt > maxt)
114             maxt = ps[i]->cnt;
115     printf("%d\n", maxt);
116     for (int i = 1; i <= n; i++)
117         if (ps[i]->cnt == maxt)
118             puts(T[i]);
119 }
120 
121 int main() {
122     while(init())
123         solve();
124     return 0;
125 }

转载于:https://www.cnblogs.com/yyf0309/p/8640939.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是NSGA-II算法的Python代码(附有注释): ```python import random import numpy as np # 定义一个类来表示每个个体 class Individual: def __init__(self, x, y): self.x = x self.y = y self.rank = None self.crowding_distance = None # 计算个体的适应度函数值 def evaluate(self): self.fitness = [self.x**2, self.y**2] # 初始化种群 def initialize_population(pop_size): population = [] for i in range(pop_size): x = random.uniform(-5, 5) y = random.uniform(-5, 5) individual = Individual(x, y) individual.evaluate() population.append(individual) return population # 计算支配关系 def dominates(x, y): return all(x_i >= y_i for x_i, y_i in zip(x.fitness, y.fitness)) and any(x_i > y_i for x_i, y_i in zip(x.fitness, y.fitness)) # 计算非支配排序 def non_dominated_sort(population): # 存储支配个体的数量 domination_count = [0] * len(population) # 存储每个个体被哪些个体支配 dominated_individuals = [[] for _ in range(len(population))] # 存储每个个体支配的个体 dominating_individuals = [[] for _ in range(len(population))] # 存储每个个体的等级 ranks = [None] * len(population) # 第一层中的个体没有被任何个体支配 front_1 = [] for i, individual in enumerate(population): for j, other_individual in enumerate(population): if i == j: continue if dominates(individual, other_individual): # i 支配 j dominating_individuals[i].append(j) dominated_individuals[j].append(i) elif dominates(other_individual, individual): # i 被 j 支配 domination_count[i] += 1 if domination_count[i] == 0: ranks[i] = 1 front_1.append(i) fronts = [front_1] current_front = 0 while True: next_front = [] for i in fronts[current_front]: for j in dominating_individuals[i]: domination_count[j] -= 1 if domination_count[j] == 0: ranks[j] = current_front + 2 next_front.append(j) if not next_front: break fronts.append(next_front) current_front += 1 for i, individual in enumerate(population): individual.rank = ranks[i] return fronts # 计算拥挤度 def crowding_distance(front): distances = [0] * len(front) # 对每个目标函数都进行排序 for i in range(2): front.sort(key=lambda individual: individual.fitness[i]) distances[0] = distances[-1] = float('inf') fitness_range = front[-1].fitness[i] - front[0].fitness[i] # 计算每个个体的拥挤度 for j in range(1, len(front) - 1): distances[j] += (front[j+1].fitness[i] - front[j-1].fitness[i]) / fitness_range for i, individual in enumerate(front): individual.crowding_distance = distances[i] # 计算新的种群 def reproduce(fronts, pop_size): new_population = [] current_size = 0 front_index = 0 # 按照等级从前往后遍历每一层 while current_size < pop_size and front_index < len(fronts): # 如果加入这一层的所有个体总数小于等于种群大小,则全部加入新种群 if current_size + len(fronts[front_index]) <= pop_size: for individual_index in fronts[front_index]: new_population.append(population[individual_index]) current_size += 1 front_index += 1 else: # 否则,按照拥挤度选择部分个体加入新种群 crowding_distances = [individual.crowding_distance for individual in fronts[front_index]] sort_order = np.argsort(crowding_distances)[::-1] for i in sort_order: new_population.append(population[fronts[front_index][i]]) current_size += 1 if current_size == pop_size: break front_index += 1 return new_population # 初始化种群 population = initialize_population(100) # 迭代次数 num_generations = 50 # 进化 for generation in range(num_generations): fronts = non_dominated_sort(population) for front in fronts: crowding_distance(front) population = reproduce(fronts, len(population)) # 输出 Pareto 最优解 pareto_front = non_dominated_sort(population)[0] for index in pareto_front: print(population[index].fitness)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值