BestCoder Round #74 (div.2) -LCP Array(有毒的模拟)

本文介绍了一种基于字符串的LCPArray问题,讨论了如何通过分析最长公共前缀来确定可能的字符串组合数量,并提供了解决方案及代码实现。

LCP Array

 
 Accepts: 131
 
 Submissions: 1352
 Time Limit: 4000/2000 MS (Java/Others)
 
 Memory Limit: 131072/131072 K (Java/Others)
问题描述
Peter有一个字符串s=s_{1}s_{2}...s_{n}s=s1s2...sn, 令\text{suff}_i =s_{i}s_{i+1}...s_{n}suffi=sisi+1...snssii字符开头的后缀. Peter知道任意两个相邻的后缀的最长公共前缀a_i = \text{lcp}(\text{suff}_i, \text{suff}_{i+1}) \quad (1 \le i < nai=lcp(suffi,suffi+1)(1i<n).

现在给你数组aa, Peter有多少个仅包含小写字母的字符串满足这个数组. 答案也许会很大, 你只要输出对10^9 + 7109+7取模的结果即可.
输入描述
输入包含多组数据. 第一行有一个整数TT, 表示测试数据的组数. 对于每组数据:

第一行包含一个整数nn (2 \le n \le 10^5)2n105)表示字符串的长度. 第二行包含n - 1n1个整数: a_1,a_2,...,a_{n-1}a1,a2,...,an1 (0 \le a_i \le n)(0ain).

所有数据中nn的和不超过10^6106.
输出描述
对于每组数据, 输出答案对10^9+7109+7取模的结果.
输入样例
3
3
0 0
4
3 2 1
3
1 2
输出样例
16250
26
0

思路:

LCP Array

如果a_i=xai=x, 那么可以推断出s_i=s_{i+1}=...=s_{i+x}si=si+1=...=si+x, 并且如果a_i \ne 0ai0, 那么a_{i+1}=a_i-1ai+1=ai1, 利用第二个条件判断无解, 利用第一个条件划分等价类. 假设有mm个等价类, 那么答案就是26\cdot 25^{m-1}2625m1


第一题就花了一个多钟才A真的是有毒,漏了个k>n-i还Wa了。。。。。

AC代码:
#include<iostream>
#include<functional>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<cstdio>
#include<cmath>
#include<map>
using namespace std;
#define CRL(a) memset(a,0,sizeof(a))
#define QWQ ios::sync_with_stdio(0)
typedef unsigned long long LL;
typedef  long long ll;
#define CMP bool cmp(const node& a,const node& b){    return a.R<b.R||(a.R==b.R&&a.L<b.L); }
const int T = 100000+50;
const int mod = 1000000007;


int main()
{

#ifdef zsc
    freopen("input.txt","r",stdin);
#endif

    int i,k,n,t,cnt,cur,c;
    scanf("%d",&t);

    while(t--)
    {
        cnt = cur = 0;
        scanf("%d",&n);
        bool f1;
        f1 = false;
        c = 0;
        for(i=1;i<n;++i){
            scanf("%d",&k);
            if(cur&&cur-k!=1||k>n-i)f1 = true;//不是1,0的情况
            if(cur&&!k)c++;//1,0的情况
            else if(k==0)cnt++;//0,0的情况
            cur = k;//保存上一次的值
        }
        if(f1){
            printf("0\n");
        }
        else if(c+1==n&&!cnt){
            printf("26\n");
        }
        else {
            ll sum = 26;
            for(i=1;i<=c+cnt;++i){
                sum = sum*25%mod;
            }
            printf("%I64d\n",sum);
        }
    }

    return 0;
}



​ 前言 JavaScript作为现代Web应用的核心技术,其性能直接影响用户体验。随着应用复杂度增加,性能优化成为开发者必须掌握的技能。本文将从多个维度深入探讨JavaScript性能优化的实战策略和技巧。 一、代码层面优化 1.1 减少DOM操作 DOM操作是JavaScript中最耗性能的操作之一,应尽量减少DOM访问和修改次数。 实战技巧: // 不佳实践:频繁操作DOM for (let i = 0; i < 1000; i++) { document.getElementById(&#39;list&#39;).innerHTML += `<li>Item ${i}</li>`; } // 优化实践:使用文档片段批量操作 const fragment = document.createDocumentFragment(); for (let i = 0; i < 1000; i++) { const li = document.createElement(&#39;li&#39;); li.textContent = `Item ${i}`; fragment.appendChild(li); } document.getElementById(&#39;list&#39;).appendChild(fragment); 1.2 事件委托 利用事件冒泡机制,减少事件处理器的数量。 // 不佳实践:为每个元素绑定事件 document.querySelectorAll(&#39;.item&#39;).forEach(item => { item.addEventListener(&#39;click&#39;, handleClick); }); // 优化实践:事件委托 document.getElementById(&#39;container&#39;).addEventListener(&#39;click&#39;, (e) => { if (e.target.classList.contains(&#39;item&#39;)) { handleClick(e); } }); 1.3 避免不必要的计算 缓存重复使用的计算结果和DOM查询。 // 不佳实践:重复计算和查询 function calculateWidth() { const element = document.getElementById(&#39;content&#39;); return element.offsetWidth * 0.8; } // 优化实践:缓存结果 let cachedWidth = null; function calculateWidth() { if (cachedWidth === null) { const element = document.getElementById(&#39;content&#39;); cachedWidth = element.offsetWidth * 0.8; } return cachedWidth; } 1.4 使用Web Worker处理密集型任务 将CPU密集型任务转移到Web Worker,避免阻塞主线程。 // 主线程代码 const worker = new Worker(&#39;task.js&#39;); worker.postMessage({ data: largeData }); worker.onmessage = (e) => { console.log(&#39;Result:&#39;, e.data); }; // task.js self.onmessage = (e) => { const result = processLargeData(e.data); self.postMessage(result); }; 二、内存管理优化 2.1 避免内存泄漏 常见内存泄漏场景及解决方案: // 1. 意外的全局变量 function leak() { leakedVar = &#39;这是一个全局变量&#39;; // 未使用var/let/const } // 2. 被遗忘的定时器 const intervalId = setInterval(() => { // 操作... }, 1000); // 需要时清除:clearInterval(intervalId); // 3. DOM引用 const elements = { button: document.getElementById(&#39;button&#39;) }; // 即使从DOM移除,elements.button仍保留引用 2.2 合理使用对象池 对于频繁创建和销毁的对象,使用对象池技术。 class ObjectPool { constructor(createFn) { this.createFn = createFn; this.pool = []; } get() { return this.pool.length > 0 ? this.pool.pop() : this.createFn(); } release(obj) { this.pool.push(obj); } } // 使用示例 const particlePool = new ObjectPool(() => ({ x: 0, y: 0, vx: 0, vy: 0, active: false })); 三、网络性能优化 3.1 代码拆分与懒加载 使用动态import实现按需加载。 // 静态导入 // import { heavyModule } from &#39;./heavy-module&#39;; // 动态导入(懒加载) button.addEventListener(&#39;click&#39;, async () => { const { heavyModule } = await import(&#39;./heavy-module&#39;); heavyModule.doWork(); }); 3.2 资源预加载 使用<link rel="preload">或Resource Hints。 <!-- 预加载关键资源 --> <link rel="preload" href="critical.js" as="script"> <link rel="preload" href="important.css" as="style"> 四、渲染性能优化 4.1 减少重绘和回流 优化策略: // 不佳实践:多次修改样式引起多次回流 element.style.width = &#39;100px&#39;; element.style.height = &#39;200px&#39;; element.style.margin = &#39;10px&#39;; // 优化实践1:使用cssText批量修改 element.style.cssText = &#39;width: 100px; height: 200px; margin: 10px;&#39;; // 优化实践2:使用classList element.classList.add(&#39;new-style&#39;); // 优化实践3:离线DOM操作 const container = document.getElementById(&#39;container&#39;); container.style.display = &#39;none&#39;; // 批量DOM操作... container.style.display = &#39;block&#39;; 4.2 使用requestAnimationFrame 优化动画性能,确保与浏览器刷新率同步。 function animate() { // 动画逻辑 requestAnimationFrame(animate); } requestAnimationFrame(animate); 4.3 使用WebGL进行复杂图形处理 对于数据可视化、游戏等高性能图形需求,考虑使用WebGL。 五、算法与数据结构优化 5.1 选择合适的数据结构 根据场景选择最优数据结构。 // 需要快速查找时使用Set/Map const largeSet = new Set(largeArray); console.log(largeSet.has(&#39;target&#39;)); // O(1)时间复杂度 // 需要有序数据时使用数组 const sortedArray = [...largeSet].sort(); 5.2 优化循环性能 // 不佳实践:在循环中执行昂贵操作 for (let i = 0; i < array.length; i++) { expensiveOperation(array[i]); } // 优化实践1:缓存长度 for (let i = 0, len = array.length; i < len; i++) { expensiveOperation(array[i]); } // 优化实践2:使用更快的循环方法 array.forEach(item => { expensiveOperation(item); }); 六、工具与监控 6.1 性能分析工具 6.2 实时性能监控 // 监控长任务 const observer = new PerformanceObserver((list) => { for (const entry of list.getEntries()) { if (entry.duration > 50) { console.warn(&#39;长任务 detected:&#39;, entry); } } }); observer.observe({ entryTypes: [&#39;longtask&#39;] }); // 监控FPS let frameCount = 0; let lastTime = performance.now(); function checkFPS() { frameCount++; const currentTime = performance.now(); if (currentTime - lastTime >= 1000) { const fps = Math.round((frameCount * 1000) / (currentTime - lastTime)); if (fps < 30) { console.warn(&#39;低FPS:&#39;, fps); } frameCount = 0; lastTime = currentTime; } requestAnimationFrame(checkFPS); } checkFPS(); 七、框架特定优化 7.1 React优化实践 // 使用React.memo避免不必要的重渲染 const ExpensiveComponent = React.memo(({ data }) => { // 组件逻辑 }); // 使用useCallback和useMemo缓存值和函数 const memoizedCallback = useCallback(() => { doSomething(a, b); }, [a, b]); const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]); 7.2 Vue优化实践 // 使用v-once和v-memo <template> <div v-memo="[value]"> {{ value }} </div> </template> // 合理使用计算属性 computed: { optimizedData() { // 只有依赖变化时才重新计算 return this.heavyComputation(this.sourceData); } } 总结 JavaScript性能优化是一个持续的过程,需要开发者从多个维度综合考虑。关键点包括: 性能优化不是一蹴而就的,应该在开发过程中持续关注,并通过测试确保优化效果。记住,最好的优化往往是那些不需要复杂技巧的简单改进——比如删除不必要的代码或选择更高效的算法。 延伸阅读 通过实践这些优化技巧,您可以显著提升JavaScript应用的性能,为用户提供更流畅的体验。 ​生成思维导图
最新发布
09-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值